summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiao Ma <xiaom@google.com>2020-04-16 05:56:41 +0000
committerXiao Ma <xiaom@google.com>2020-04-16 06:43:56 +0000
commit39cd852a2060a579a79db2740e52b2c7129a3845 (patch)
treea0715af2b78d2fb02b307513295ef03236c8b5c6
parent9aef7f0ee06f4715e5e447303752f33656689d91 (diff)
Renew previous IP address when roaming happens in certain specific Wi-Fi networks.
Bug: 131797393 Test: atest NetworkStackTests NetworkStackIntegrationTests Test: atest FrameworksNetTests Merged-In: I65ebdd142a2bb402035c63cd282bc2574ddf3d8d Change-Id: I65ebdd142a2bb402035c63cd282bc2574ddf3d8d
-rw-r--r--src/android/net/dhcp/DhcpClient.java6
-rw-r--r--src/android/net/dhcp/DhcpPacket.java3
-rw-r--r--src/android/net/ip/IpClient.java72
-rw-r--r--tests/integration/src/android/net/ip/IpClientIntegrationTest.java163
4 files changed, 216 insertions, 28 deletions
diff --git a/src/android/net/dhcp/DhcpClient.java b/src/android/net/dhcp/DhcpClient.java
index 41e54a4..23e68fa 100644
--- a/src/android/net/dhcp/DhcpClient.java
+++ b/src/android/net/dhcp/DhcpClient.java
@@ -233,6 +233,9 @@ public class DhcpClient extends StateMachine {
public static final int CMD_START_PRECONNECTION = PUBLIC_BASE + 10;
public static final int CMD_ABORT_PRECONNECTION = PUBLIC_BASE + 11;
+ // Command to rebind the leased IPv4 address on L2 roaming happened.
+ public static final int CMD_REFRESH_LINKADDRESS = PUBLIC_BASE + 12;
+
/* Message.arg1 arguments to CMD_POST_DHCP_ACTION notification */
public static final int DHCP_SUCCESS = 1;
public static final int DHCP_FAILURE = 2;
@@ -1674,6 +1677,9 @@ public class DhcpClient extends StateMachine {
case CMD_RENEW_DHCP:
preDhcpTransitionTo(mWaitBeforeRenewalState, mDhcpRenewingState);
return HANDLED;
+ case CMD_REFRESH_LINKADDRESS:
+ transitionTo(mDhcpRebindingState);
+ return HANDLED;
default:
return NOT_HANDLED;
}
diff --git a/src/android/net/dhcp/DhcpPacket.java b/src/android/net/dhcp/DhcpPacket.java
index a695060..852719e 100644
--- a/src/android/net/dhcp/DhcpPacket.java
+++ b/src/android/net/dhcp/DhcpPacket.java
@@ -335,7 +335,8 @@ public abstract class DhcpPacket {
* proposed by the client (from an earlier DHCP negotiation) or
* supplied by the server.
*/
- protected final Inet4Address mClientIp;
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ public final Inet4Address mClientIp;
protected final Inet4Address mYourIp;
private final Inet4Address mNextIp;
protected final Inet4Address mRelayIp;
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java
index 9ad2c78..4ddcc13 100644
--- a/src/android/net/ip/IpClient.java
+++ b/src/android/net/ip/IpClient.java
@@ -32,6 +32,7 @@ import android.net.Layer2InformationParcelable;
import android.net.Layer2PacketParcelable;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.MacAddress;
import android.net.NattKeepalivePacketDataParcelable;
import android.net.NetworkStackIpMemoryStore;
import android.net.ProvisioningConfigurationParcelable;
@@ -92,6 +93,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -381,7 +383,8 @@ public class IpClient extends StateMachine {
private static final int CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF = 13;
private static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF = 14;
private static final int CMD_UPDATE_L2KEY_GROUPHINT = 15;
- protected static final int CMD_COMPLETE_PRECONNECTION = 16;
+ private static final int CMD_COMPLETE_PRECONNECTION = 16;
+ private static final int CMD_UPDATE_L2INFORMATION = 17;
// Internal commands to use instead of trying to call transitionTo() inside
// a given State's enter() method. Calling transitionTo() from enter/exit
@@ -423,6 +426,14 @@ public class IpClient extends StateMachine {
new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xf2, (byte) 0x06 }
));
+ // Initialize configurable particular SSID set supporting DHCP Roaming feature. See
+ // b/131797393 for more details.
+ private static final Set<String> DHCP_ROAMING_SSID_SET = new HashSet<>(
+ Arrays.asList(
+ "0001docomo", "ollehWiFi", "olleh GiGa WiFi", "KT WiFi",
+ "KT GiGA WiFi", "marente"
+ ));
+
private final State mStoppedState = new StoppedState();
private final State mStoppingState = new StoppingState();
private final State mClearingIpAddressesState = new ClearingIpAddressesState();
@@ -470,6 +481,7 @@ public class IpClient extends StateMachine {
private String mGroupHint; // The group hint for this network, for writing into the memory store
private boolean mMulticastFiltering;
private long mStartTimeMillis;
+ private MacAddress mCurrentBssid;
/**
* Reading the snapshot is an asynchronous operation initiated by invoking
@@ -704,7 +716,6 @@ public class IpClient extends StateMachine {
enforceNetworkStackCallingPermission();
IpClient.this.notifyPreconnectionComplete(success);
}
-
@Override
public void updateLayer2Information(Layer2InformationParcelable info) {
enforceNetworkStackCallingPermission();
@@ -772,6 +783,16 @@ public class IpClient extends StateMachine {
return;
}
+ final ScanResultInfo scanResultInfo = req.mScanResultInfo;
+ mCurrentBssid = null;
+ if (scanResultInfo != null) {
+ try {
+ mCurrentBssid = MacAddress.fromString(scanResultInfo.getBssid());
+ } catch (IllegalArgumentException e) {
+ Log.wtf(mTag, "Invalid BSSID: " + scanResultInfo.getBssid()
+ + " in provisioning configuration", e);
+ }
+ }
sendMessage(CMD_START, new android.net.shared.ProvisioningConfiguration(req));
}
@@ -819,9 +840,14 @@ public class IpClient extends StateMachine {
/**
* Set the L2 key and group hint for storing info into the memory store.
+ *
+ * This method is only supported on Q devices. For R or above releases,
+ * caller should call #updateLayer2Information() instead.
*/
public void setL2KeyAndGroupHint(String l2Key, String groupHint) {
- sendMessage(CMD_UPDATE_L2KEY_GROUPHINT, new Pair<>(l2Key, groupHint));
+ if (!ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) {
+ sendMessage(CMD_UPDATE_L2KEY_GROUPHINT, new Pair<>(l2Key, groupHint));
+ }
}
/**
@@ -880,7 +906,7 @@ public class IpClient extends StateMachine {
* Update the network bssid, L2Key and GroupHint layer2 information.
*/
public void updateLayer2Information(@NonNull Layer2InformationParcelable info) {
- // TODO: add specific implementation.
+ sendMessage(CMD_UPDATE_L2INFORMATION, info);
}
/**
@@ -1502,6 +1528,36 @@ public class IpClient extends StateMachine {
}
}
+ private void handleUpdateL2Information(@NonNull Layer2InformationParcelable info) {
+ mL2Key = info.l2Key;
+ mGroupHint = info.groupHint;
+
+ // This means IpClient is still in the StoppedState, WiFi is trying to associate
+ // to the AP, just update L2Key and GroupHint at this stage, because these members
+ // will be used when starting DhcpClient.
+ if (info.bssid == null || mCurrentBssid == null) return;
+
+ // If the BSSID has not changed, there is nothing to do.
+ if (info.bssid.equals(mCurrentBssid)) return;
+
+ if (mIpReachabilityMonitor != null) {
+ mIpReachabilityMonitor.probeAll();
+ }
+
+ // Check whether to refresh previous IP lease on L2 roaming happened.
+ final String ssid = removeDoubleQuotes(mConfiguration.mDisplayName);
+ if (DHCP_ROAMING_SSID_SET.contains(ssid) && mDhcpClient != null) {
+ if (DBG) {
+ Log.d(mTag, "L2 roaming happened from " + mCurrentBssid
+ + " to " + info.bssid
+ + " , SSID: " + ssid
+ + " , starting refresh leased IP address");
+ }
+ mDhcpClient.sendMessage(DhcpClient.CMD_REFRESH_LINKADDRESS);
+ }
+ mCurrentBssid = info.bssid;
+ }
+
class StoppedState extends State {
@Override
public void enter() {
@@ -1554,6 +1610,10 @@ public class IpClient extends StateMachine {
break;
}
+ case CMD_UPDATE_L2INFORMATION:
+ handleUpdateL2Information((Layer2InformationParcelable) msg.obj);
+ break;
+
case CMD_SET_MULTICAST_FILTER:
mMulticastFiltering = (boolean) msg.obj;
break;
@@ -1763,6 +1823,10 @@ public class IpClient extends StateMachine {
break;
}
+ case CMD_UPDATE_L2INFORMATION:
+ handleUpdateL2Information((Layer2InformationParcelable) msg.obj);
+ break;
+
case EVENT_PROVISIONING_TIMEOUT:
handleProvisioningFailure();
break;
diff --git a/tests/integration/src/android/net/ip/IpClientIntegrationTest.java b/tests/integration/src/android/net/ip/IpClientIntegrationTest.java
index ce2efbb..56ad6c1 100644
--- a/tests/integration/src/android/net/ip/IpClientIntegrationTest.java
+++ b/tests/integration/src/android/net/ip/IpClientIntegrationTest.java
@@ -24,7 +24,6 @@ import static android.net.dhcp.DhcpPacket.DHCP_SERVER;
import static android.net.dhcp.DhcpPacket.ENCAP_L2;
import static android.net.dhcp.DhcpPacket.INADDR_BROADCAST;
import static android.net.dhcp.DhcpPacket.INFINITE_LEASE;
-import static android.net.ip.IpClient.removeDoubleQuotes;
import static android.net.ipmemorystore.Status.SUCCESS;
import static android.net.shared.Inet4AddressUtils.getBroadcastAddress;
import static android.net.shared.Inet4AddressUtils.getPrefixMaskAsInet4Address;
@@ -49,7 +48,6 @@ import static com.android.server.util.NetworkStackConstants.ICMPV6_ROUTER_SOLICI
import static com.android.server.util.NetworkStackConstants.IPV6_HEADER_LEN;
import static com.android.server.util.NetworkStackConstants.IPV6_LEN_OFFSET;
import static com.android.server.util.NetworkStackConstants.IPV6_PROTOCOL_OFFSET;
-import static com.android.server.util.NetworkStackConstants.VENDOR_SPECIFIC_IE_ID;
import static junit.framework.Assert.fail;
@@ -87,6 +85,7 @@ import android.net.INetd;
import android.net.InetAddresses;
import android.net.InterfaceConfigurationParcel;
import android.net.IpPrefix;
+import android.net.Layer2InformationParcelable;
import android.net.Layer2PacketParcelable;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -217,6 +216,8 @@ public class IpClientIntegrationTest {
(Inet4Address) InetAddresses.parseNumericAddress("192.168.1.100");
private static final Inet4Address CLIENT_ADDR =
(Inet4Address) InetAddresses.parseNumericAddress("192.168.1.2");
+ private static final Inet4Address CLIENT_ADDR_NEW =
+ (Inet4Address) InetAddresses.parseNumericAddress("192.168.1.3");
private static final Inet4Address INADDR_ANY =
(Inet4Address) InetAddresses.parseNumericAddress("0.0.0.0");
private static final int PREFIX_LENGTH = 24;
@@ -234,7 +235,14 @@ public class IpClientIntegrationTest {
(byte) 0x00, (byte) 0x17, (byte) 0xF2
};
private static final byte TEST_VENDOR_SPECIFIC_TYPE = 0x06;
+
+ private static final String TEST_DEFAULT_SSID = "test_ssid";
private static final String TEST_DEFAULT_BSSID = "00:11:22:33:44:55";
+ private static final String TEST_DHCP_ROAM_SSID = "0001docomo";
+ private static final String TEST_DHCP_ROAM_BSSID = "00:4e:35:17:98:55";
+ private static final String TEST_DHCP_ROAM_L2KEY = "roaming_l2key";
+ private static final String TEST_DHCP_ROAM_GROUPHINT = "roaming_group_hint";
+ private static final byte[] TEST_AP_OUI = new byte[] { 0x00, 0x1A, 0x11 };
private class Dependencies extends IpClient.Dependencies {
private boolean mIsDhcpLeaseCacheEnabled;
@@ -473,11 +481,11 @@ public class IpClientIntegrationTest {
}
private static ByteBuffer buildDhcpAckPacket(final DhcpPacket packet,
- final Integer leaseTimeSec, final short mtu, final boolean rapidCommit,
- final String captivePortalApiUrl) {
+ final Inet4Address clientAddress, final Integer leaseTimeSec, final short mtu,
+ final boolean rapidCommit, final String captivePortalApiUrl) {
return DhcpPacket.buildAckPacket(DhcpPacket.ENCAP_L2, packet.getTransactionId(),
false /* broadcast */, SERVER_ADDR, INADDR_ANY /* relayIp */,
- CLIENT_ADDR /* yourIp */, CLIENT_ADDR /* requestIp */, packet.getClientMac(),
+ clientAddress /* yourIp */, CLIENT_ADDR /* requestIp */, packet.getClientMac(),
leaseTimeSec, NETMASK /* netMask */, BROADCAST_ADDR /* bcAddr */,
Collections.singletonList(SERVER_ADDR) /* gateways */,
Collections.singletonList(SERVER_ADDR) /* dnsServers */,
@@ -524,7 +532,15 @@ public class IpClientIntegrationTest {
mDependencies.setDhcpRapidCommitEnabled(shouldReplyRapidCommitAck);
mDependencies.setDhcpIpConflictDetectEnabled(isDhcpIpConflictDetectEnabled);
mDependencies.setHostnameConfiguration(isHostnameConfigurationEnabled, hostname);
- mIpc.setL2KeyAndGroupHint(TEST_L2KEY, TEST_GROUPHINT);
+
+ if (ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) {
+ final Layer2InformationParcelable info = new Layer2InformationParcelable();
+ info.l2Key = TEST_L2KEY;
+ info.groupHint = TEST_GROUPHINT;
+ mIpc.updateLayer2Information(info);
+ } else {
+ mIpc.setL2KeyAndGroupHint(TEST_L2KEY, TEST_GROUPHINT);
+ }
mIpc.startProvisioning(builder.build());
if (!isPreconnectionEnabled) {
verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false);
@@ -616,15 +632,15 @@ public class IpClientIntegrationTest {
packetList.add(packet);
if (packet instanceof DhcpDiscoverPacket) {
if (shouldReplyRapidCommitAck) {
- mPacketReader.sendResponse(buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu,
- true /* rapidCommit */, captivePortalApiUrl));
+ mPacketReader.sendResponse(buildDhcpAckPacket(packet, CLIENT_ADDR, leaseTimeSec,
+ (short) mtu, true /* rapidCommit */, captivePortalApiUrl));
} else {
mPacketReader.sendResponse(buildDhcpOfferPacket(packet, leaseTimeSec,
(short) mtu, captivePortalApiUrl));
}
} else if (packet instanceof DhcpRequestPacket) {
final ByteBuffer byteBuffer = isSuccessLease
- ? buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu,
+ ? buildDhcpAckPacket(packet, CLIENT_ADDR, leaseTimeSec, (short) mtu,
false /* rapidCommit */, captivePortalApiUrl)
: buildDhcpNakPacket(packet);
mPacketReader.sendResponse(byteBuffer);
@@ -810,8 +826,8 @@ public class IpClientIntegrationTest {
packet = getNextDhcpPacket();
assertTrue(packet instanceof DhcpRequestPacket);
}
- mPacketReader.sendResponse(buildDhcpAckPacket(packet, TEST_LEASE_DURATION_S, mtu,
- shouldReplyRapidCommitAck, null /* captivePortalUrl */));
+ mPacketReader.sendResponse(buildDhcpAckPacket(packet, CLIENT_ADDR, TEST_LEASE_DURATION_S,
+ mtu, shouldReplyRapidCommitAck, null /* captivePortalUrl */));
if (!shouldAbortPreconnection) {
mIpc.notifyPreconnectionComplete(true /* success */);
@@ -1590,9 +1606,15 @@ public class IpClientIntegrationTest {
return new ScanResultInfo(ssid, bssid, Collections.singletonList(ie));
}
+ private ScanResultInfo makeScanResultInfo(final String ssid, final String bssid) {
+ byte[] data = new byte[10];
+ new Random().nextBytes(data);
+ return makeScanResultInfo(0xdd, ssid, bssid, TEST_AP_OUI, (byte) 0x06, data);
+ }
+
private void doUpstreamHotspotDetectionTest(final int id, final String displayName,
- final String ssid, final byte[] oui, final byte type, final byte[] data)
- throws Exception {
+ final String ssid, final byte[] oui, final byte type, final byte[] data,
+ final boolean expectMetered) throws Exception {
final ScanResultInfo info = makeScanResultInfo(id, ssid, TEST_DEFAULT_BSSID, oui, type,
data);
final long currentTime = System.currentTimeMillis();
@@ -1615,10 +1637,8 @@ public class IpClientIntegrationTest {
assertTrue(lease.getDnsServers().contains(SERVER_ADDR));
assertEquals(lease.getServerAddress(), SERVER_ADDR);
assertEquals(lease.getMtu(), TEST_DEFAULT_MTU);
- if (id == VENDOR_SPECIFIC_IE_ID
- && ssid.equals(removeDoubleQuotes(displayName))
- && Arrays.equals(oui, TEST_HOTSPOT_OUI)
- && type == TEST_VENDOR_SPECIFIC_TYPE) {
+
+ if (expectMetered) {
assertEquals(lease.vendorInfo, DhcpPacket.VENDOR_INFO_ANDROID_METERED);
} else {
assertNull(lease.vendorInfo);
@@ -1632,7 +1652,8 @@ public class IpClientIntegrationTest {
byte[] data = new byte[10];
new Random().nextBytes(data);
doUpstreamHotspotDetectionTest(0xdd, "\"ssid\"", "ssid",
- new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xF2 }, (byte) 0x06, data);
+ new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xF2 }, (byte) 0x06, data,
+ true /* expectMetered */);
}
@Test
@@ -1640,7 +1661,8 @@ public class IpClientIntegrationTest {
byte[] data = new byte[10];
new Random().nextBytes(data);
doUpstreamHotspotDetectionTest(0xdc, "\"ssid\"", "ssid",
- new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xF2 }, (byte) 0x06, data);
+ new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xF2 }, (byte) 0x06, data,
+ false /* expectMetered */);
}
@Test
@@ -1648,7 +1670,8 @@ public class IpClientIntegrationTest {
byte[] data = new byte[10];
new Random().nextBytes(data);
doUpstreamHotspotDetectionTest(0xdd, "\"ssid\"", "ssid",
- new byte[] { (byte) 0x00, (byte) 0x1A, (byte) 0x11 }, (byte) 0x06, data);
+ new byte[] { (byte) 0x00, (byte) 0x1A, (byte) 0x11 }, (byte) 0x06, data,
+ false /* expectMetered */);
}
@Test
@@ -1656,7 +1679,8 @@ public class IpClientIntegrationTest {
byte[] data = new byte[10];
new Random().nextBytes(data);
doUpstreamHotspotDetectionTest(0xdd, "\"another ssid\"", "ssid",
- new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xF2 }, (byte) 0x06, data);
+ new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xF2 }, (byte) 0x06, data,
+ false /* expectMetered */);
}
@Test
@@ -1664,13 +1688,106 @@ public class IpClientIntegrationTest {
byte[] data = new byte[10];
new Random().nextBytes(data);
doUpstreamHotspotDetectionTest(0xdd, "\"ssid\"", "ssid",
- new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xF2 }, (byte) 0x0a, data);
+ new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xF2 }, (byte) 0x0a, data,
+ false /* expectMetered */);
}
@Test
public void testUpstreamHotspotDetection_zeroLengthData() throws Exception {
byte[] data = new byte[0];
doUpstreamHotspotDetectionTest(0xdd, "\"ssid\"", "ssid",
- new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xF2 }, (byte) 0x06, data);
+ new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xF2 }, (byte) 0x06, data,
+ true /* expectMetered */);
+ }
+
+ private void doDhcpRoamingTest(final boolean hasMismatchedIpAddress, final String displayName,
+ final String ssid, final String bssid, final boolean expectRoaming) throws Exception {
+ long currentTime = System.currentTimeMillis();
+ final ScanResultInfo scanResultInfo = makeScanResultInfo(ssid, bssid);
+
+ doAnswer(invocation -> {
+ // we don't rely on the Init-Reboot state to renew previous cached IP lease.
+ // Just return null and force state machine enter INIT state.
+ return null;
+ }).when(mIpMemoryStore).retrieveNetworkAttributes(eq(TEST_L2KEY), any());
+
+ performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S,
+ true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */,
+ TEST_DEFAULT_MTU, false /* isDhcpIpConflictDetectEnabled */,
+ true /* isHostnameConfigurationEnabled */, null /* hostname */,
+ null /* captivePortalApiUrl */, displayName, scanResultInfo);
+ assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, TEST_DEFAULT_MTU);
+
+ // simulate the roaming by updating bssid.
+ final Layer2InformationParcelable roamingInfo = new Layer2InformationParcelable();
+ roamingInfo.bssid = MacAddress.fromString(TEST_DHCP_ROAM_BSSID);
+ roamingInfo.l2Key = TEST_DHCP_ROAM_L2KEY;
+ roamingInfo.groupHint = TEST_DHCP_ROAM_GROUPHINT;
+ mIpc.updateLayer2Information(roamingInfo);
+
+ currentTime = System.currentTimeMillis();
+ reset(mIpMemoryStore);
+ reset(mCb);
+ if (!expectRoaming) {
+ assertIpMemoryNeverStoreNetworkAttributes();
+ return;
+ }
+ // check DHCPREQUEST broadcast sent to renew IP address.
+ DhcpPacket packet;
+ packet = getNextDhcpPacket();
+ assertTrue(packet instanceof DhcpRequestPacket);
+ assertEquals(packet.mClientIp, CLIENT_ADDR); // client IP
+ assertNull(packet.mRequestedIp); // requested IP option
+ assertNull(packet.mServerIdentifier); // server ID
+
+ mPacketReader.sendResponse(buildDhcpAckPacket(packet,
+ hasMismatchedIpAddress ? CLIENT_ADDR_NEW : CLIENT_ADDR, TEST_LEASE_DURATION_S,
+ (short) TEST_DEFAULT_MTU, false /* rapidcommit */, null /* captivePortalUrl */));
+ HandlerUtilsKt.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS);
+ if (hasMismatchedIpAddress) {
+ // notifyFailure
+ ArgumentCaptor<DhcpResultsParcelable> captor =
+ ArgumentCaptor.forClass(DhcpResultsParcelable.class);
+ verify(mCb, timeout(TEST_TIMEOUT_MS)).onNewDhcpResults(captor.capture());
+ DhcpResults lease = fromStableParcelable(captor.getValue());
+ assertNull(lease);
+
+ // roll back to INIT state.
+ packet = getNextDhcpPacket();
+ assertTrue(packet instanceof DhcpDiscoverPacket);
+ } else {
+ assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime,
+ TEST_DEFAULT_MTU);
+ }
+ }
+
+ @Test
+ public void testDhcpRoaming() throws Exception {
+ doDhcpRoamingTest(false /* hasMismatchedIpAddress */, "\"0001docomo\"" /* display name */,
+ TEST_DHCP_ROAM_SSID, TEST_DEFAULT_BSSID, true /* expectRoaming */);
+ }
+
+ @Test
+ public void testDhcpRoaming_invalidBssid() throws Exception {
+ doDhcpRoamingTest(false /* hasMismatchedIpAddress */, "\"0001docomo\"" /* display name */,
+ TEST_DHCP_ROAM_SSID, TEST_DHCP_ROAM_BSSID, false /* expectRoaming */);
+ }
+
+ @Test
+ public void testDhcpRoaming_invalidSsid() throws Exception {
+ doDhcpRoamingTest(false /* hasMismatchedIpAddress */, "\"0001docomo\"" /* display name */,
+ TEST_DEFAULT_SSID, TEST_DEFAULT_BSSID, false /* expectRoaming */);
+ }
+
+ @Test
+ public void testDhcpRoaming_invalidDisplayName() throws Exception {
+ doDhcpRoamingTest(false /* hasMismatchedIpAddress */, "\"test-ssid\"" /* display name */,
+ TEST_DHCP_ROAM_SSID, TEST_DEFAULT_BSSID, false /* expectRoaming */);
+ }
+
+ @Test
+ public void testDhcpRoaming_mismatchedLeasedIpAddress() throws Exception {
+ doDhcpRoamingTest(true /* hasMismatchedIpAddress */, "\"0001docomo\"" /* display name */,
+ TEST_DHCP_ROAM_SSID, TEST_DEFAULT_BSSID, true /* expectRoaming */);
}
}