Merge "Add more test coverage to ConnectivityManagerTest." into nyc-dev
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 4112466..231db97 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -38,9 +38,16 @@
import android.test.AndroidTestCase;
import android.util.Log;
import android.os.SystemProperties;
+import android.system.Os;
+import android.system.OsConstants;
import com.android.internal.telephony.PhoneConstants;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -57,7 +64,15 @@
public static final int TYPE_MOBILE = ConnectivityManager.TYPE_MOBILE;
public static final int TYPE_WIFI = ConnectivityManager.TYPE_WIFI;
+
private static final int HOST_ADDRESS = 0x7f000001;// represent ip 127.0.0.1
+ private static final String TEST_HOST = "connectivitycheck.gstatic.com";
+ private static final int SOCKET_TIMEOUT_MS = 2000;
+ private static final int HTTP_PORT = 80;
+ private static final String HTTP_REQUEST =
+ "GET /generate_204 HTTP/1.0\r\n" +
+ "Host: " + TEST_HOST + "\r\n" +
+ "Connection: keep-alive\r\n\r\n";
// Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
private static final String NETWORK_CALLBACK_ACTION =
@@ -249,6 +264,12 @@
mCm.getBackgroundDataSetting();
}
+ private NetworkRequest makeWifiNetworkRequest() {
+ return new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .build();
+ }
+
/**
* Exercises both registerNetworkCallback and unregisterNetworkCallback. This checks to
* see if we get a callback for the TRANSPORT_WIFI transport type being available.
@@ -265,16 +286,14 @@
}
// We will register for a WIFI network being available or lost.
- final NetworkRequest request = new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .build();
final TestNetworkCallback callback = new TestNetworkCallback();
- mCm.registerNetworkCallback(request, callback);
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
final TestNetworkCallback defaultTrackingCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultTrackingCallback);
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
+ Network wifiNetwork = null;
try {
// Make sure WiFi is connected to an access point to start with.
@@ -285,10 +304,11 @@
// Now we should expect to get a network callback about availability of the wifi
// network even if it was already connected as a state-based action when the callback
// is registered.
- assertTrue("Did not receive NetworkCallback.onAvailable for TRANSPORT_WIFI",
- callback.waitForAvailable());
+ wifiNetwork = callback.waitForAvailable();
+ assertNotNull("Did not receive NetworkCallback.onAvailable for TRANSPORT_WIFI",
+ wifiNetwork);
- assertTrue("Did not receive NetworkCallback.onAvailable for any default network",
+ assertNotNull("Did not receive NetworkCallback.onAvailable for any default network",
defaultTrackingCallback.waitForAvailable());
} catch (InterruptedException e) {
fail("Broadcast receiver or NetworkCallback wait was interrupted.");
@@ -298,7 +318,7 @@
// Return WiFi to its original enabled/disabled state.
if (!previousWifiEnabledState) {
- disconnectFromWifi();
+ disconnectFromWifi(wifiNetwork);
}
}
}
@@ -329,10 +349,7 @@
mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
// We will register for a WIFI network being available or lost.
- NetworkRequest request = new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .build();
- mCm.registerNetworkCallback(request, pendingIntent);
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), pendingIntent);
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
@@ -356,7 +373,7 @@
// Return WiFi to its original enabled/disabled state.
if (!previousWifiEnabledState) {
- disconnectFromWifi();
+ disconnectFromWifi(null);
}
}
}
@@ -370,8 +387,10 @@
// We will toggle the state of wifi to generate a connectivity change.
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
+
if (previousWifiEnabledState) {
- disconnectFromWifi();
+ Network wifiNetwork = getWifiNetwork();
+ disconnectFromWifi(wifiNetwork);
} else {
connectToWifi();
}
@@ -387,12 +406,16 @@
if (previousWifiEnabledState) {
connectToWifi();
} else {
- disconnectFromWifi();
+ disconnectFromWifi(null);
}
}
/** Enable WiFi and wait for it to become connected to a network. */
- private void connectToWifi() {
+ private Network connectToWifi() {
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
+ Network wifiNetwork = null;
+
ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED);
IntentFilter filter = new IntentFilter();
@@ -402,36 +425,94 @@
boolean connected = false;
try {
assertTrue(mWifiManager.setWifiEnabled(true));
+ // Ensure we get both an onAvailable callback and a CONNECTIVITY_ACTION.
+ wifiNetwork = callback.waitForAvailable();
+ assertNotNull(wifiNetwork);
connected = receiver.waitForState();
} catch (InterruptedException ex) {
fail("connectToWifi was interrupted");
} finally {
+ mCm.unregisterNetworkCallback(callback);
mContext.unregisterReceiver(receiver);
}
assertTrue("Wifi must be configured to connect to an access point for this test.",
connected);
+ return wifiNetwork;
+ }
+
+ private Socket getBoundSocket(Network network, String host, int port) throws IOException {
+ InetSocketAddress addr = new InetSocketAddress(host, port);
+ Socket s = network.getSocketFactory().createSocket();
+ try {
+ s.setSoTimeout(SOCKET_TIMEOUT_MS);
+ s.connect(addr, SOCKET_TIMEOUT_MS);
+ } catch (IOException e) {
+ s.close();
+ throw e;
+ }
+ return s;
+ }
+
+ private void testHttpRequest(Socket s) throws IOException {
+ OutputStream out = s.getOutputStream();
+ InputStream in = s.getInputStream();
+
+ final byte[] requestBytes = HTTP_REQUEST.getBytes("UTF-8");
+ byte[] responseBytes = new byte[4096];
+ out.write(requestBytes);
+ in.read(responseBytes);
+ assertTrue(new String(responseBytes, "UTF-8").startsWith("HTTP/1.0 204 No Content\r\n"));
}
/** Disable WiFi and wait for it to become disconnected from the network. */
- private void disconnectFromWifi() {
+ private void disconnectFromWifi(Network wifiNetworkToCheck) {
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
+ Network lostWifiNetwork = null;
+
ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
ConnectivityManager.TYPE_WIFI, NetworkInfo.State.DISCONNECTED);
IntentFilter filter = new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mContext.registerReceiver(receiver, filter);
+ // Assert that we can establish a TCP connection on wifi.
+ Socket wifiBoundSocket = null;
+ if (wifiNetworkToCheck != null) {
+ try {
+ wifiBoundSocket = getBoundSocket(wifiNetworkToCheck, TEST_HOST, HTTP_PORT);
+ testHttpRequest(wifiBoundSocket);
+ } catch (IOException e) {
+ fail("HTTP request before wifi disconnected failed with: " + e);
+ }
+ }
+
boolean disconnected = false;
try {
assertTrue(mWifiManager.setWifiEnabled(false));
+ // Ensure we get both an onLost callback and a CONNECTIVITY_ACTION.
+ lostWifiNetwork = callback.waitForLost();
+ assertNotNull(lostWifiNetwork);
disconnected = receiver.waitForState();
} catch (InterruptedException ex) {
fail("disconnectFromWifi was interrupted");
} finally {
+ mCm.unregisterNetworkCallback(callback);
mContext.unregisterReceiver(receiver);
}
assertTrue("Wifi failed to reach DISCONNECTED state.", disconnected);
+
+ // Check that the socket is closed when wifi disconnects.
+ if (wifiBoundSocket != null) {
+ try {
+ testHttpRequest(wifiBoundSocket);
+ fail("HTTP request should not succeed after wifi disconnects");
+ } catch (IOException expected) {
+ assertEquals(Os.strerror(OsConstants.ECONNABORTED), expected.getMessage());
+ }
+ }
}
/**
@@ -498,15 +579,48 @@
*/
private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
private final CountDownLatch mAvailableLatch = new CountDownLatch(1);
+ private final CountDownLatch mLostLatch = new CountDownLatch(1);
- public boolean waitForAvailable() throws InterruptedException {
- return mAvailableLatch.await(30, TimeUnit.SECONDS);
+ public Network currentNetwork;
+ public Network lastLostNetwork;
+
+ public Network waitForAvailable() throws InterruptedException {
+ return mAvailableLatch.await(30, TimeUnit.SECONDS) ? currentNetwork : null;
+ }
+
+ public Network waitForLost() throws InterruptedException {
+ return mLostLatch.await(30, TimeUnit.SECONDS) ? lastLostNetwork : null;
}
@Override
public void onAvailable(Network network) {
+ currentNetwork = network;
mAvailableLatch.countDown();
}
+
+ @Override
+ public void onLost(Network network) {
+ lastLostNetwork = network;
+ if (network.equals(currentNetwork)) {
+ currentNetwork = null;
+ }
+ mLostLatch.countDown();
+ }
+ }
+
+ private Network getWifiNetwork() {
+ TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
+ Network network = null;
+ try {
+ network = callback.waitForAvailable();
+ } catch (InterruptedException e) {
+ fail("NetworkCallback wait was interrupted.");
+ } finally {
+ mCm.unregisterNetworkCallback(callback);
+ }
+ assertNotNull("Cannot find Network for wifi. Is wifi connected?", network);
+ return network;
}
/** Verify restricted networks cannot be requested. */
@@ -523,8 +637,6 @@
try {
mCm.requestNetwork(request, callback);
fail("No exception thrown when restricted network requested.");
- } catch (SecurityException e) {
- // Expected.
- }
+ } catch (SecurityException expected) {}
}
}