Merge "Fix EntitlementManager issues"
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 0c37235..0cfd884 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -16,9 +16,7 @@
java_defaults {
name: "TetheringAndroidLibraryDefaults",
- // TODO (b/146757305): change to module API once available
- // TODO (b/148190005): change to module-libs-api-stubs-current once it is ready.
- sdk_version: "core_platform",
+ sdk_version: "module_current",
srcs: [
"src/**/*.java",
":framework-tethering-shared-srcs",
@@ -35,15 +33,8 @@
"net-utils-framework-common",
],
libs: [
- // Order matters: framework-tethering needs to be before the system stubs, otherwise
- // hidden fields in the framework-tethering classes (which are also used to generate stubs)
- // will not be found.
"framework-tethering",
- "android_system_stubs_current",
- "framework-res",
"unsupportedappusage",
- "android_system_stubs_current",
- "framework-res",
],
plugins: ["java_api_finder"],
manifest: "AndroidManifestBase.xml",
@@ -91,9 +82,7 @@
// Common defaults for compiling the actual APK.
java_defaults {
name: "TetheringAppDefaults",
- // TODO (b/146757305): change to module API once available
- // TODO (b/148190005): change to module-libs-api-stubs-current once it is ready.
- sdk_version: "core_platform",
+ sdk_version: "module_current",
privileged: true,
jni_libs: [
"libtetherutilsjni",
@@ -102,12 +91,7 @@
"res",
],
libs: [
- // Order matters: framework-tethering needs to be before the system stubs, otherwise
- // hidden fields in the framework-tethering classes (which are also used to generate stubs)
- // will not be found.
"framework-tethering",
- "android_system_stubs_current",
- "framework-res",
],
jarjar_rules: "jarjar-rules.txt",
optimize: {
diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp
index 00d0d9c..31c40d2 100644
--- a/Tethering/common/TetheringLib/Android.bp
+++ b/Tethering/common/TetheringLib/Android.bp
@@ -65,12 +65,7 @@
stubs_defaults {
name: "framework-tethering-stubs-defaults",
- srcs: [
- "src/android/net/TetheredClient.java",
- "src/android/net/TetheringManager.java",
- "src/android/net/TetheringConstants.java",
- ],
- libs: ["tethering-aidl-interfaces-java"],
+ srcs: [":framework-tethering-srcs"],
}
filegroup {
@@ -126,17 +121,17 @@
java_library {
name: "framework-tethering-stubs-publicapi",
srcs: [":framework-tethering-stubs-srcs-publicapi"],
- sdk_version: "current",
+ defaults: ["framework-module-stubs-lib-defaults-publicapi"],
}
java_library {
name: "framework-tethering-stubs-systemapi",
srcs: [":framework-tethering-stubs-srcs-systemapi"],
- sdk_version: "system_current",
+ defaults: ["framework-module-stubs-lib-defaults-systemapi"],
}
java_library {
name: "framework-tethering-stubs-module_libs_api",
srcs: [":framework-tethering-stubs-srcs-module_libs_api"],
- sdk_version: "module_current",
+ defaults: ["framework-module-stubs-lib-defaults-systemapi"],
}
diff --git a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index 096f4fe..0107a7e 100644
--- a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -571,9 +571,8 @@
/**
* Configure tethering with static IPv4 assignment.
*
- * The clientAddress must be in the localIPv4Address prefix. A DHCP server will be
- * started, but will only be able to offer the client address. The two addresses must
- * be in the same prefix.
+ * A DHCP server will be started, but will only be able to offer the client address.
+ * The two addresses must be in the same prefix.
*
* @param localIPv4Address The preferred local IPv4 link address to use.
* @param clientAddress The static client address.
@@ -584,10 +583,7 @@
@NonNull final LinkAddress clientAddress) {
Objects.requireNonNull(localIPv4Address);
Objects.requireNonNull(clientAddress);
- if (localIPv4Address.getPrefixLength() != clientAddress.getPrefixLength()
- || !localIPv4Address.isIpv4() || !clientAddress.isIpv4()
- || !new IpPrefix(localIPv4Address.toString()).equals(
- new IpPrefix(clientAddress.toString()))) {
+ if (!checkStaticAddressConfiguration(localIPv4Address, clientAddress)) {
throw new IllegalArgumentException("Invalid server or client addresses");
}
@@ -657,6 +653,19 @@
}
/**
+ * Check whether the two addresses are ipv4 and in the same prefix.
+ * @hide
+ */
+ public static boolean checkStaticAddressConfiguration(
+ @NonNull final LinkAddress localIPv4Address,
+ @NonNull final LinkAddress clientAddress) {
+ return localIPv4Address.getPrefixLength() == clientAddress.getPrefixLength()
+ && localIPv4Address.isIpv4() && clientAddress.isIpv4()
+ && new IpPrefix(localIPv4Address.toString()).equals(
+ new IpPrefix(clientAddress.toString()));
+ }
+
+ /**
* Get a TetheringRequestParcel from the configuration
* @hide
*/
diff --git a/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java b/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
index d6bc063..82a26be 100644
--- a/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
+++ b/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
@@ -18,10 +18,12 @@
import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH;
-import android.annotation.NonNull;
import android.net.LinkAddress;
import android.util.ArraySet;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import java.net.Inet4Address;
import java.util.Collection;
import java.util.Collections;
@@ -160,6 +162,17 @@
return this;
}
+ /**
+ * Set the client address to tell DHCP server only offer this address.
+ * The client's prefix length is the same as server's.
+ *
+ * <p>If not set, the default value is null.
+ */
+ public DhcpServingParamsParcelExt setSingleClientAddr(@Nullable Inet4Address clientAddr) {
+ this.clientAddr = clientAddr == null ? 0 : inet4AddressToIntHTH(clientAddr);
+ return this;
+ }
+
private static int[] toIntArray(@NonNull Collection<Inet4Address> addrs) {
int[] res = new int[addrs.size()];
int i = 0;
diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java
index c5478d2..82b17ac 100644
--- a/Tethering/src/android/net/ip/IpServer.java
+++ b/Tethering/src/android/net/ip/IpServer.java
@@ -18,6 +18,7 @@
import static android.net.InetAddresses.parseNumericAddress;
import static android.net.RouteInfo.RTN_UNICAST;
+import static android.net.TetheringManager.TetheringRequest.checkStaticAddressConfiguration;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
import static android.net.util.NetworkConstants.FF;
@@ -492,17 +493,24 @@
}
}
- private boolean startDhcp(Inet4Address addr, int prefixLen) {
+ private boolean startDhcp(final LinkAddress serverLinkAddr, final LinkAddress clientLinkAddr) {
if (mUsingLegacyDhcp) {
return true;
}
+
+ final Inet4Address addr = (Inet4Address) serverLinkAddr.getAddress();
+ final int prefixLen = serverLinkAddr.getPrefixLength();
+ final Inet4Address clientAddr = clientLinkAddr == null ? null :
+ (Inet4Address) clientLinkAddr.getAddress();
+
final DhcpServingParamsParcel params;
params = new DhcpServingParamsParcelExt()
.setDefaultRouters(addr)
.setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS)
.setDnsServers(addr)
- .setServerAddr(new LinkAddress(addr, prefixLen))
- .setMetered(true);
+ .setServerAddr(serverLinkAddr)
+ .setMetered(true)
+ .setSingleClientAddr(clientAddr);
// TODO: also advertise link MTU
mDhcpServerStartIndex++;
@@ -537,9 +545,10 @@
}
}
- private boolean configureDhcp(boolean enable, Inet4Address addr, int prefixLen) {
+ private boolean configureDhcp(boolean enable, final LinkAddress serverAddr,
+ final LinkAddress clientAddr) {
if (enable) {
- return startDhcp(addr, prefixLen);
+ return startDhcp(serverAddr, clientAddr);
} else {
stopDhcp();
return true;
@@ -587,7 +596,7 @@
// code that calls into NetworkManagementService directly.
srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
mIpv4Address = new LinkAddress(srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
- return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
+ return configureDhcp(enabled, mIpv4Address, null /* clientAddress */);
}
mIpv4Address = new LinkAddress(srvAddr, prefixLen);
} catch (IllegalArgumentException e) {
@@ -624,7 +633,7 @@
mLinkProperties.removeRoute(route);
}
- return configureDhcp(enabled, srvAddr, prefixLen);
+ return configureDhcp(enabled, mIpv4Address, mStaticIpv4ClientAddr);
}
private String getRandomWifiIPv4Address() {
@@ -945,7 +954,14 @@
}
private void maybeConfigureStaticIp(final TetheringRequestParcel request) {
- if (request == null) return;
+ // Ignore static address configuration if they are invalid or null. In theory, static
+ // addresses should not be invalid here because TetheringManager do not allow caller to
+ // specify invalid static address configuration.
+ if (request == null || request.localIPv4Address == null
+ || request.staticClientAddress == null || !checkStaticAddressConfiguration(
+ request.localIPv4Address, request.staticClientAddress)) {
+ return;
+ }
mStaticIpv4ServerAddr = request.localIPv4Address;
mStaticIpv4ClientAddr = request.staticClientAddress;
diff --git a/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 7ac7f5f..45bb4ab 100644
--- a/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -586,21 +586,21 @@
*/
@VisibleForTesting
public static NetworkCapabilities networkCapabilitiesForType(int type) {
- final NetworkCapabilities nc = new NetworkCapabilities();
+ final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder();
// Map from type to transports.
final int notFound = -1;
final int transport = sLegacyTypeToTransport.get(type, notFound);
Preconditions.checkArgument(transport != notFound, "unknown legacy type: " + type);
- nc.addTransportType(transport);
+ builder.addTransportType(transport);
if (type == TYPE_MOBILE_DUN) {
- nc.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
+ builder.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
// DUN is restricted network, see NetworkCapabilities#FORCE_RESTRICTED_CAPABILITIES.
- nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
} else {
- nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
}
- return nc;
+ return builder.build();
}
}
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index 843a4f1..dbd68ef 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.net.TetheringManager.TETHERING_ETHERNET;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -57,14 +58,17 @@
import java.io.FileDescriptor;
import java.net.Inet4Address;
+import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.List;
import java.util.Random;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
@RunWith(AndroidJUnit4.class)
@MediumTest
@@ -109,7 +113,7 @@
}
private void cleanUp() throws Exception {
- mTm.stopTethering(TetheringManager.TETHERING_ETHERNET);
+ mTm.stopTethering(TETHERING_ETHERNET);
if (mTetheringEventCallback != null) {
mTetheringEventCallback.awaitInterfaceUntethered();
mTetheringEventCallback.unregister();
@@ -150,10 +154,7 @@
Log.d(TAG, "Including test interfaces");
mEm.setIncludeTestInterfaces(true);
- Log.d(TAG, "Requesting tethered interface");
- mTetheredInterfaceRequester.requestInterface();
-
- final String iface = mTetheredInterfaceRequester.awaitRequestedInterface();
+ final String iface = mTetheredInterfaceRequester.getInterface();
assertEquals("TetheredInterfaceCallback for unexpected interface",
mTestIface.getInterfaceName(), iface);
@@ -165,14 +166,13 @@
// This test requires manipulating packets. Skip if there is a physical Ethernet connected.
assumeFalse(mEm.isAvailable());
- Log.d(TAG, "Requesting tethered interface");
- mTetheredInterfaceRequester.requestInterface();
+ CompletableFuture<String> futureIface = mTetheredInterfaceRequester.requestInterface();
mEm.setIncludeTestInterfaces(true);
mTestIface = createTestInterface();
- final String iface = mTetheredInterfaceRequester.awaitRequestedInterface();
+ final String iface = futureIface.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
assertEquals("TetheredInterfaceCallback for unexpected interface",
mTestIface.getInterfaceName(), iface);
@@ -180,12 +180,54 @@
}
@Test
+ public void testStaticIpv4() throws Exception {
+ assumeFalse(mEm.isAvailable());
+
+ mEm.setIncludeTestInterfaces(true);
+
+ mTestIface = createTestInterface();
+
+ final String iface = mTetheredInterfaceRequester.getInterface();
+ assertEquals("TetheredInterfaceCallback for unexpected interface",
+ mTestIface.getInterfaceName(), iface);
+
+ assertInvalidStaticIpv4Request(iface, null, null);
+ assertInvalidStaticIpv4Request(iface, "2001:db8::1/64", "2001:db8:2::/64");
+ assertInvalidStaticIpv4Request(iface, "192.0.2.2/28", "2001:db8:2::/28");
+ assertInvalidStaticIpv4Request(iface, "2001:db8:2::/28", "192.0.2.2/28");
+ assertInvalidStaticIpv4Request(iface, "192.0.2.2/28", null);
+ assertInvalidStaticIpv4Request(iface, null, "192.0.2.2/28");
+ assertInvalidStaticIpv4Request(iface, "192.0.2.3/27", "192.0.2.2/28");
+
+ final String localAddr = "192.0.2.3/28";
+ final String clientAddr = "192.0.2.2/28";
+ mTetheringEventCallback = enableEthernetTethering(iface,
+ requestWithStaticIpv4(localAddr, clientAddr));
+
+ mTetheringEventCallback.awaitInterfaceTethered();
+ assertInterfaceHasIpAddress(iface, clientAddr);
+
+ byte[] client1 = MacAddress.fromString("1:2:3:4:5:6").toByteArray();
+ byte[] client2 = MacAddress.fromString("a:b:c:d:e:f").toByteArray();
+
+ FileDescriptor fd = mTestIface.getFileDescriptor().getFileDescriptor();
+ mTapPacketReader = makePacketReader(fd, getMTU(mTestIface));
+ DhcpResults dhcpResults = runDhcp(fd, client1);
+ assertEquals(new LinkAddress(clientAddr), dhcpResults.ipAddress);
+
+ try {
+ runDhcp(fd, client2);
+ fail("Only one client should get an IP address");
+ } catch (TimeoutException expected) { }
+
+ }
+
+ @Test
public void testPhysicalEthernet() throws Exception {
assumeTrue(mEm.isAvailable());
// Get an interface to use.
- mTetheredInterfaceRequester.requestInterface();
- String iface = mTetheredInterfaceRequester.awaitRequestedInterface();
+ final String iface = mTetheredInterfaceRequester.getInterface();
// Enable Ethernet tethering and check that it starts.
mTetheringEventCallback = enableEthernetTethering(iface);
@@ -275,7 +317,8 @@
}
}
- private MyTetheringEventCallback enableEthernetTethering(String iface) throws Exception {
+ private MyTetheringEventCallback enableEthernetTethering(String iface,
+ TetheringRequest request) throws Exception {
MyTetheringEventCallback callback = new MyTetheringEventCallback(mTm, iface);
mTm.registerTetheringEventCallback(mHandler::post, callback);
@@ -286,34 +329,37 @@
}
};
Log.d(TAG, "Starting Ethernet tethering");
- mTm.startTethering(
- new TetheringRequest.Builder(TetheringManager.TETHERING_ETHERNET).build(),
- mHandler::post /* executor */, startTetheringCallback);
+ mTm.startTethering(request, mHandler::post /* executor */, startTetheringCallback);
callback.awaitInterfaceTethered();
return callback;
}
+ private MyTetheringEventCallback enableEthernetTethering(String iface) throws Exception {
+ return enableEthernetTethering(iface,
+ new TetheringRequest.Builder(TETHERING_ETHERNET).build());
+ }
+
private int getMTU(TestNetworkInterface iface) throws SocketException {
NetworkInterface nif = NetworkInterface.getByName(iface.getInterfaceName());
assertNotNull("Can't get NetworkInterface object for " + iface.getInterfaceName(), nif);
return nif.getMTU();
}
+ private TapPacketReader makePacketReader(FileDescriptor fd, int mtu) {
+ final TapPacketReader reader = new TapPacketReader(mHandler, fd, mtu);
+ mHandler.post(() -> reader.start());
+ HandlerUtilsKt.waitForIdle(mHandler, TIMEOUT_MS);
+ return reader;
+ }
+
private void checkVirtualEthernet(TestNetworkInterface iface, int mtu) throws Exception {
FileDescriptor fd = iface.getFileDescriptor().getFileDescriptor();
- mTapPacketReader = new TapPacketReader(mHandler, fd, mtu);
- mHandler.post(() -> mTapPacketReader.start());
- HandlerUtilsKt.waitForIdle(mHandler, TIMEOUT_MS);
-
+ mTapPacketReader = makePacketReader(fd, mtu);
mTetheringEventCallback = enableEthernetTethering(iface.getInterfaceName());
checkTetheredClientCallbacks(fd);
}
- private void checkTetheredClientCallbacks(FileDescriptor fd) throws Exception {
- // Create a fake client.
- byte[] clientMacAddr = new byte[6];
- new Random().nextBytes(clientMacAddr);
-
+ private DhcpResults runDhcp(FileDescriptor fd, byte[] clientMacAddr) throws Exception {
// We have to retransmit DHCP requests because IpServer declares itself to be ready before
// its DhcpServer is actually started. TODO: fix this race and remove this loop.
DhcpPacket offerPacket = null;
@@ -323,13 +369,25 @@
offerPacket = getNextDhcpPacket();
if (offerPacket instanceof DhcpOfferPacket) break;
}
- assertTrue("No DHCPOFFER received on interface within timeout",
- offerPacket instanceof DhcpOfferPacket);
+ if (!(offerPacket instanceof DhcpOfferPacket)) {
+ throw new TimeoutException("No DHCPOFFER received on interface within timeout");
+ }
sendDhcpRequest(fd, offerPacket, clientMacAddr);
DhcpPacket ackPacket = getNextDhcpPacket();
- assertTrue("No DHCPACK received on interface within timeout",
- ackPacket instanceof DhcpAckPacket);
+ if (!(ackPacket instanceof DhcpAckPacket)) {
+ throw new TimeoutException("No DHCPACK received on interface within timeout");
+ }
+
+ return ackPacket.toDhcpResults();
+ }
+
+ private void checkTetheredClientCallbacks(FileDescriptor fd) throws Exception {
+ // Create a fake client.
+ byte[] clientMacAddr = new byte[6];
+ new Random().nextBytes(clientMacAddr);
+
+ DhcpResults dhcpResults = runDhcp(fd, clientMacAddr);
final Collection<TetheredClient> clients = mTetheringEventCallback.awaitClientConnected();
assertEquals(1, clients.size());
@@ -337,7 +395,7 @@
// Check the MAC address.
assertEquals(MacAddress.fromBytes(clientMacAddr), client.getMacAddress());
- assertEquals(TetheringManager.TETHERING_ETHERNET, client.getTetheringType());
+ assertEquals(TETHERING_ETHERNET, client.getTetheringType());
// Check the hostname.
assertEquals(1, client.getAddresses().size());
@@ -345,7 +403,6 @@
assertEquals(DHCP_HOSTNAME, info.getHostname());
// Check the address is the one that was handed out in the DHCP ACK.
- DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertLinkAddressMatches(dhcpResults.ipAddress, info.getAddress());
// Check that the lifetime is correct +/- 10s.
@@ -373,8 +430,8 @@
private final Handler mHandler;
private final EthernetManager mEm;
- private volatile TetheredInterfaceRequest mRequest;
- private volatile String mIface;
+ private TetheredInterfaceRequest mRequest;
+ private final CompletableFuture<String> mFuture = new CompletableFuture<>();
TetheredInterfaceRequester(Handler handler, EthernetManager em) {
mHandler = handler;
@@ -384,25 +441,28 @@
@Override
public void onAvailable(String iface) {
Log.d(TAG, "Ethernet interface available: " + iface);
- mIface = iface;
- mInterfaceAvailableLatch.countDown();
+ mFuture.complete(iface);
}
+
@Override
- public void onUnavailable() {}
-
- public void requestInterface() {
- assertNull("BUG: more than one tethered interface request", mRequest);
- mRequest = mEm.requestTetheredInterface(mHandler::post, this);
+ public void onUnavailable() {
+ mFuture.completeExceptionally(new IllegalStateException("onUnavailable received"));
}
- public String awaitRequestedInterface() throws InterruptedException {
- assertTrue("No tethered interface available after " + TIMEOUT_MS + "ms",
- mInterfaceAvailableLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- return mIface;
+ public CompletableFuture<String> requestInterface() {
+ assertNull("BUG: more than one tethered interface request", mRequest);
+ Log.d(TAG, "Requesting tethered interface");
+ mRequest = mEm.requestTetheredInterface(mHandler::post, this);
+ return mFuture;
+ }
+
+ public String getInterface() throws Exception {
+ return requestInterface().get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
}
public void release() {
if (mRequest != null) {
+ mFuture.obtrudeException(new IllegalStateException("Request already released"));
mRequest.release();
mRequest = null;
}
@@ -442,6 +502,34 @@
assertEquals("LinkAddress scope does not match", l1.getScope(), l2.getScope());
}
+ private TetheringRequest requestWithStaticIpv4(String local, String client) {
+ LinkAddress localAddr = local == null ? null : new LinkAddress(local);
+ LinkAddress clientAddr = client == null ? null : new LinkAddress(client);
+ return new TetheringRequest.Builder(TETHERING_ETHERNET)
+ .setStaticIpv4Addresses(localAddr, clientAddr).build();
+ }
+
+ private void assertInvalidStaticIpv4Request(String iface, String local, String client)
+ throws Exception {
+ try {
+ enableEthernetTethering(iface, requestWithStaticIpv4(local, client));
+ fail("Unexpectedly accepted invalid IPv4 configuration: " + local + ", " + client);
+ } catch (IllegalArgumentException | NullPointerException expected) { }
+ }
+
+ private void assertInterfaceHasIpAddress(String iface, String expected) throws Exception {
+ LinkAddress expectedAddr = new LinkAddress(expected);
+ NetworkInterface nif = NetworkInterface.getByName(iface);
+ for (InterfaceAddress ia : nif.getInterfaceAddresses()) {
+ final LinkAddress addr = new LinkAddress(ia.getAddress(), ia.getNetworkPrefixLength());
+ if (expectedAddr.equals(addr)) {
+ return;
+ }
+ }
+ fail("Expected " + iface + " to have IP address " + expected + ", found "
+ + nif.getInterfaceAddresses());
+ }
+
private TestNetworkInterface createTestInterface() throws Exception {
TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class);
TestNetworkInterface iface = tnm.createTapInterface();
diff --git a/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java b/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
index e8add98..f8eb147 100644
--- a/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
+++ b/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
@@ -42,7 +42,9 @@
@SmallTest
public class DhcpServingParamsParcelExtTest {
private static final Inet4Address TEST_ADDRESS = inet4Addr("192.168.0.123");
+ private static final Inet4Address TEST_CLIENT_ADDRESS = inet4Addr("192.168.0.42");
private static final int TEST_ADDRESS_PARCELED = 0xc0a8007b;
+ private static final int TEST_CLIENT_ADDRESS_PARCELED = 0xc0a8002a;
private static final int TEST_PREFIX_LENGTH = 17;
private static final int TEST_LEASE_TIME_SECS = 120;
private static final int TEST_MTU = 1000;
@@ -105,6 +107,12 @@
assertFalse(mParcel.metered);
}
+ @Test
+ public void testSetClientAddr() {
+ mParcel.setSingleClientAddr(TEST_CLIENT_ADDRESS);
+ assertEquals(TEST_CLIENT_ADDRESS_PARCELED, mParcel.clientAddr);
+ }
+
private static Inet4Address inet4Addr(String addr) {
return (Inet4Address) parseNumericAddress(addr);
}
diff --git a/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index 7252737..a418c4a 100644
--- a/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -38,6 +38,7 @@
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
+import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
@@ -1654,10 +1655,13 @@
}
@Test
- public void testRequestStaticServerIp() throws Exception {
- final LinkAddress serverLinkAddr = new LinkAddress("192.168.20.1/24");
- final LinkAddress clientLinkAddr = new LinkAddress("192.168.20.42/24");
- final String serverAddr = "192.168.20.1";
+ public void testRequestStaticIp() throws Exception {
+ final LinkAddress serverLinkAddr = new LinkAddress("192.168.0.123/24");
+ final LinkAddress clientLinkAddr = new LinkAddress("192.168.0.42/24");
+ final String serverAddr = "192.168.0.123";
+ final int clientAddrParceled = 0xc0a8002a;
+ final ArgumentCaptor<DhcpServingParamsParcel> dhcpParamsCaptor =
+ ArgumentCaptor.forClass(DhcpServingParamsParcel.class);
mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
serverLinkAddr, clientLinkAddr), null);
mLooper.dispatchAll();
@@ -1666,8 +1670,12 @@
sendUsbBroadcast(true, true, true, TETHERING_USB);
mLooper.dispatchAll();
verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr)));
-
- // TODO: test static client address.
+ verify(mIpServerDependencies, times(1)).makeDhcpServer(any(), dhcpParamsCaptor.capture(),
+ any());
+ final DhcpServingParamsParcel params = dhcpParamsCaptor.getValue();
+ assertEquals(serverAddr, intToInet4AddressHTH(params.serverAddr).getHostAddress());
+ assertEquals(24, params.serverAddrPrefixLength);
+ assertEquals(clientAddrParceled, params.clientAddr);
}
// TODO: Test that a request for hotspot mode doesn't interfere with an