Fix ConnectivityManagerApi23Test failures and remove duplication.
1. All ConnectivityManagerApi23Test were failed due to
WifiManager#setWifiEnabled doesn't allow to use since
Android Q. So we need to use shell command to enable/disable
Wi-Fi instead.
2. Some methods are duplicated between
ConnectivityManagerApi23Test and ConnectivityManagerTest, but
they are not identical. So put these methods into
ConnectivityUtils to clean up duplications and prevent fork
happened again.
Bug: 133334943
Bug: 133209319
Test: Run the below tests on Crosshatch, Sailfish, Bonito.
atest CtsNetApi23TestCases
atest CtsNetTestCases
Change-Id: Ic37111cb12a46f5c36c2be887250c5d762216f6e
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index 779d5c4..b6ea4af 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -42,6 +42,7 @@
"FrameworksNetCommonTests",
"core-tests-support",
"compatibility-device-util-axt",
+ "cts-net-utils",
"ctstestrunner-axt",
"ctstestserver",
"mockwebserver",
diff --git a/tests/cts/net/api23Test/Android.bp b/tests/cts/net/api23Test/Android.bp
index 48161cf..ffe854e 100644
--- a/tests/cts/net/api23Test/Android.bp
+++ b/tests/cts/net/api23Test/Android.bp
@@ -31,6 +31,7 @@
static_libs: [
"core-tests-support",
"compatibility-device-util-axt",
+ "cts-net-utils",
"ctstestrunner-axt",
"ctstestserver",
"mockwebserver",
diff --git a/tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityManagerApi23Test.java b/tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityManagerApi23Test.java
index f38490e..cdb66e3 100644
--- a/tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityManagerApi23Test.java
+++ b/tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityManagerApi23Test.java
@@ -25,58 +25,33 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.net.NetworkInfo.State;
-import android.net.NetworkRequest;
-import android.net.wifi.WifiManager;
+import android.net.cts.util.CtsNetUtils;
import android.os.Looper;
-import android.system.Os;
-import android.system.OsConstants;
import android.test.AndroidTestCase;
import android.util.Log;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class ConnectivityManagerApi23Test extends AndroidTestCase {
private static final String TAG = ConnectivityManagerApi23Test.class.getSimpleName();
-
- private static final String TEST_HOST = "connectivitycheck.gstatic.com";
- private static final int SOCKET_TIMEOUT_MS = 2000;
private static final int SEND_BROADCAST_TIMEOUT = 30000;
- private static final int HTTP_PORT = 80;
// Intent string to get the number of wifi CONNECTIVITY_ACTION callbacks the test app has seen
public static final String GET_WIFI_CONNECTIVITY_ACTION_COUNT =
"android.net.cts.appForApi23.getWifiConnectivityActionCount";
// Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
- private static final String NETWORK_CALLBACK_ACTION =
- "ConnectivityManagerTest.NetworkCallbackAction";
- 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";
private Context mContext;
- private ConnectivityManager mCm;
- private WifiManager mWifiManager;
private PackageManager mPackageManager;
+ private CtsNetUtils mCtsNetUtils;
@Override
protected void setUp() throws Exception {
super.setUp();
Looper.prepare();
mContext = getContext();
- mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mPackageManager = mContext.getPackageManager();
+ mCtsNetUtils = new CtsNetUtils(mContext);
}
/**
@@ -89,7 +64,7 @@
}
ConnectivityReceiver.prepare();
- toggleWifi();
+ mCtsNetUtils.toggleWifi();
// The connectivity broadcast has been sent; push through a terminal broadcast
// to wait for in the receive to confirm it didn't see the connectivity change.
@@ -112,7 +87,7 @@
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
Thread.sleep(200);
- toggleWifi();
+ mCtsNetUtils.toggleWifi();
Intent getConnectivityCount = new Intent(GET_WIFI_CONNECTIVITY_ACTION_COUNT);
assertEquals(2, sendOrderedBroadcastAndReturnResultCode(
@@ -130,7 +105,7 @@
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mContext.registerReceiver(receiver, filter);
- toggleWifi();
+ mCtsNetUtils.toggleWifi();
Intent finalIntent = new Intent(ConnectivityReceiver.FINAL_ACTION);
finalIntent.setClass(mContext, ConnectivityReceiver.class);
mContext.sendBroadcast(finalIntent);
@@ -138,19 +113,6 @@
assertTrue(ConnectivityReceiver.waitForBroadcast());
}
- // Toggle WiFi twice, leaving it in the state it started in
- private void toggleWifi() {
- if (mWifiManager.isWifiEnabled()) {
- Network wifiNetwork = getWifiNetwork();
- disconnectFromWifi(wifiNetwork);
- connectToWifi();
- } else {
- connectToWifi();
- Network wifiNetwork = getWifiNetwork();
- disconnectFromWifi(wifiNetwork);
- }
- }
-
private int sendOrderedBroadcastAndReturnResultCode(
Intent intent, int timeoutMs) throws InterruptedException {
final LinkedBlockingQueue<Integer> result = new LinkedBlockingQueue<>(1);
@@ -167,233 +129,4 @@
return resultCode;
}
- 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;
- }
-
- /** Disable WiFi and wait for it to become disconnected from the network. */
- 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());
- }
- }
- }
-
- /** Enable WiFi and wait for it to become connected to a network. */
- 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();
- filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- mContext.registerReceiver(receiver, filter);
-
- 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 NetworkRequest makeWifiNetworkRequest() {
- return new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .build();
- }
-
- 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"));
- }
-
- 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;
- }
-
- /**
- * Receiver that captures the last connectivity change's network type and state. Recognizes
- * both {@code CONNECTIVITY_ACTION} and {@code NETWORK_CALLBACK_ACTION} intents.
- */
- private class ConnectivityActionReceiver extends BroadcastReceiver {
-
- private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
-
- private final int mNetworkType;
- private final NetworkInfo.State mNetState;
-
- ConnectivityActionReceiver(int networkType, NetworkInfo.State netState) {
- mNetworkType = networkType;
- mNetState = netState;
- }
-
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- NetworkInfo networkInfo = null;
-
- // When receiving ConnectivityManager.CONNECTIVITY_ACTION, the NetworkInfo parcelable
- // is stored in EXTRA_NETWORK_INFO. With a NETWORK_CALLBACK_ACTION, the Network is
- // sent in EXTRA_NETWORK and we need to ask the ConnectivityManager for the NetworkInfo.
- if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
- networkInfo = intent.getExtras()
- .getParcelable(ConnectivityManager.EXTRA_NETWORK_INFO);
- assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK_INFO", networkInfo);
- } else if (NETWORK_CALLBACK_ACTION.equals(action)) {
- Network network = intent.getExtras()
- .getParcelable(ConnectivityManager.EXTRA_NETWORK);
- assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK", network);
- networkInfo = mCm.getNetworkInfo(network);
- if (networkInfo == null) {
- // When disconnecting, it seems like we get an intent sent with an invalid
- // Network; that is, by the time we call ConnectivityManager.getNetworkInfo(),
- // it is invalid. Ignore these.
- Log.i(TAG, "ConnectivityActionReceiver NETWORK_CALLBACK_ACTION ignoring "
- + "invalid network");
- return;
- }
- } else {
- fail("ConnectivityActionReceiver received unxpected intent action: " + action);
- }
-
- assertNotNull("ConnectivityActionReceiver didn't find NetworkInfo", networkInfo);
- int networkType = networkInfo.getType();
- State networkState = networkInfo.getState();
- Log.i(TAG, "Network type: " + networkType + " state: " + networkState);
- if (networkType == mNetworkType && networkInfo.getState() == mNetState) {
- mReceiveLatch.countDown();
- }
- }
-
- public boolean waitForState() throws InterruptedException {
- return mReceiveLatch.await(30, TimeUnit.SECONDS);
- }
- }
-
- /**
- * Callback used in testRegisterNetworkCallback that allows caller to block on
- * {@code onAvailable}.
- */
- private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
- private final CountDownLatch mAvailableLatch = new CountDownLatch(1);
- private final CountDownLatch mLostLatch = new CountDownLatch(1);
- private final CountDownLatch mUnavailableLatch = new CountDownLatch(1);
-
- 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;
- }
-
- public boolean waitForUnavailable() throws InterruptedException {
- return mUnavailableLatch.await(2, TimeUnit.SECONDS);
- }
-
-
- @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();
- }
-
- @Override
- public void onUnavailable() {
- mUnavailableLatch.countDown();
- }
- }
}
\ No newline at end of file
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index c444445..c3ae793 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -21,8 +21,12 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.cts.util.CtsNetUtils.ConnectivityActionReceiver;
+import static android.net.cts.util.CtsNetUtils.HTTP_PORT;
+import static android.net.cts.util.CtsNetUtils.NETWORK_CALLBACK_ACTION;
+import static android.net.cts.util.CtsNetUtils.TEST_HOST;
+import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
import static android.system.OsConstants.AF_INET;
@@ -34,7 +38,6 @@
import android.app.Instrumentation;
import android.app.PendingIntent;
import android.app.UiAutomation;
-import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -53,6 +56,7 @@
import android.net.NetworkInfo.State;
import android.net.NetworkRequest;
import android.net.SocketKeepalive;
+import android.net.cts.util.CtsNetUtils;
import android.net.util.KeepaliveUtils;
import android.net.wifi.WifiManager;
import android.os.Looper;
@@ -61,15 +65,12 @@
import android.os.SystemProperties;
import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
-import android.system.Os;
-import android.system.OsConstants;
import android.test.AndroidTestCase;
import android.text.TextUtils;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
-import com.android.compatibility.common.util.SystemUtil;
import com.android.internal.R;
import com.android.internal.telephony.PhoneConstants;
@@ -107,8 +108,6 @@
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 CONNECT_TIMEOUT_MS = 2000;
private static final int KEEPALIVE_CALLBACK_TIMEOUT_MS = 2000;
private static final int KEEPALIVE_SOCKET_TIMEOUT_MS = 5000;
@@ -116,16 +115,6 @@
private static final int NETWORK_CHANGE_METEREDNESS_TIMEOUT = 5000;
private static final int NUM_TRIES_MULTIPATH_PREF_CHECK = 20;
private static final long INTERVAL_MULTIPATH_PREF_CHECK_MS = 500;
- 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 =
- "ConnectivityManagerTest.NetworkCallbackAction";
-
// device could have only one interface: data, wifi.
private static final int MIN_NUM_NETWORK_TYPES = 1;
@@ -137,8 +126,8 @@
private final HashMap<Integer, NetworkConfig> mNetworks =
new HashMap<Integer, NetworkConfig>();
boolean mWifiConnectAttempted;
- private TestNetworkCallback mCellNetworkCallback;
private UiAutomation mUiAutomation;
+ private CtsNetUtils mCtsNetUtils;
private boolean mShellPermissionIdentityAdopted;
@Override
@@ -150,6 +139,7 @@
mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mPackageManager = mContext.getPackageManager();
+ mCtsNetUtils = new CtsNetUtils(mContext);
mWifiConnectAttempted = false;
// Get com.android.internal.R.array.networkAttributes
@@ -174,10 +164,10 @@
protected void tearDown() throws Exception {
// Return WiFi to its original disabled state after tests that explicitly connect.
if (mWifiConnectAttempted) {
- disconnectFromWifi(null);
+ mCtsNetUtils.disconnectFromWifi(null);
}
- if (cellConnectAttempted()) {
- disconnectFromCell();
+ if (mCtsNetUtils.cellConnectAttempted()) {
+ mCtsNetUtils.disconnectFromCell();
}
dropShellPermissionIdentity();
super.tearDown();
@@ -190,10 +180,10 @@
*/
private Network ensureWifiConnected() {
if (mWifiManager.isWifiEnabled()) {
- return getWifiNetwork();
+ return mCtsNetUtils.getWifiNetwork();
}
mWifiConnectAttempted = true;
- return connectToWifi();
+ return mCtsNetUtils.connectToWifi();
}
public void testIsNetworkTypeValid() {
@@ -301,8 +291,8 @@
return;
}
- Network wifiNetwork = connectToWifi();
- Network cellNetwork = connectToCell();
+ Network wifiNetwork = mCtsNetUtils.connectToWifi();
+ Network cellNetwork = mCtsNetUtils.connectToCell();
// This server returns the requestor's IP address as the response body.
URL url = new URL("http://google-ipv6test.appspot.com/ip.js?fmt=text");
String wifiAddressString = httpGet(wifiNetwork, url);
@@ -320,33 +310,6 @@
assertFalse("Unexpectedly equal: " + wifiNetwork, wifiNetwork.equals(cellNetwork));
}
- private Network connectToCell() throws InterruptedException {
- if (cellConnectAttempted()) {
- throw new IllegalStateException("Already connected");
- }
- NetworkRequest cellRequest = new NetworkRequest.Builder()
- .addTransportType(TRANSPORT_CELLULAR)
- .addCapability(NET_CAPABILITY_INTERNET)
- .build();
- mCellNetworkCallback = new TestNetworkCallback();
- mCm.requestNetwork(cellRequest, mCellNetworkCallback);
- final Network cellNetwork = mCellNetworkCallback.waitForAvailable();
- assertNotNull("Cell network not available within timeout", cellNetwork);
- return cellNetwork;
- }
-
- private boolean cellConnectAttempted() {
- return mCellNetworkCallback != null;
- }
-
- private void disconnectFromCell() {
- if (!cellConnectAttempted()) {
- throw new IllegalStateException("Cell connection not attempted");
- }
- mCm.unregisterNetworkCallback(mCellNetworkCallback);
- mCellNetworkCallback = null;
- }
-
/**
* Performs a HTTP GET to the specified URL on the specified Network, and returns
* the response body decoded as UTF-8.
@@ -508,7 +471,7 @@
filter.addAction(NETWORK_CALLBACK_ACTION);
ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
- ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED);
+ mCm, ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED);
mContext.registerReceiver(receiver, filter);
// Create a broadcast PendingIntent for NETWORK_CALLBACK_ACTION.
@@ -567,7 +530,7 @@
public void testRequestNetworkCallback_onUnavailable() {
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
if (previousWifiEnabledState) {
- disconnectFromWifi(null);
+ mCtsNetUtils.disconnectFromWifi(null);
}
final TestNetworkCallback callback = new TestNetworkCallback();
@@ -584,42 +547,11 @@
} finally {
mCm.unregisterNetworkCallback(callback);
if (previousWifiEnabledState) {
- connectToWifi();
+ mCtsNetUtils.connectToWifi();
}
}
}
- /** Enable WiFi and wait for it to become connected to a network. */
- 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();
- filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- mContext.registerReceiver(receiver, filter);
-
- boolean connected = false;
- try {
- SystemUtil.runShellCommand("svc wifi enable");
- // 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 InetAddress getFirstV4Address(Network network) {
LinkProperties linkProperties = mCm.getLinkProperties(network);
for (InetAddress address : linkProperties.getAddresses()) {
@@ -630,199 +562,6 @@
return null;
}
- 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(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 {
- SystemUtil.runShellCommand("svc wifi disable");
- // 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());
- }
- }
- }
-
- /**
- * Receiver that captures the last connectivity change's network type and state. Recognizes
- * both {@code CONNECTIVITY_ACTION} and {@code NETWORK_CALLBACK_ACTION} intents.
- */
- private class ConnectivityActionReceiver extends BroadcastReceiver {
-
- private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
-
- private final int mNetworkType;
- private final NetworkInfo.State mNetState;
-
- ConnectivityActionReceiver(int networkType, NetworkInfo.State netState) {
- mNetworkType = networkType;
- mNetState = netState;
- }
-
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- NetworkInfo networkInfo = null;
-
- // When receiving ConnectivityManager.CONNECTIVITY_ACTION, the NetworkInfo parcelable
- // is stored in EXTRA_NETWORK_INFO. With a NETWORK_CALLBACK_ACTION, the Network is
- // sent in EXTRA_NETWORK and we need to ask the ConnectivityManager for the NetworkInfo.
- if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
- networkInfo = intent.getExtras()
- .getParcelable(ConnectivityManager.EXTRA_NETWORK_INFO);
- assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK_INFO", networkInfo);
- } else if (NETWORK_CALLBACK_ACTION.equals(action)) {
- Network network = intent.getExtras()
- .getParcelable(ConnectivityManager.EXTRA_NETWORK);
- assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK", network);
- networkInfo = mCm.getNetworkInfo(network);
- if (networkInfo == null) {
- // When disconnecting, it seems like we get an intent sent with an invalid
- // Network; that is, by the time we call ConnectivityManager.getNetworkInfo(),
- // it is invalid. Ignore these.
- Log.i(TAG, "ConnectivityActionReceiver NETWORK_CALLBACK_ACTION ignoring "
- + "invalid network");
- return;
- }
- } else {
- fail("ConnectivityActionReceiver received unxpected intent action: " + action);
- }
-
- assertNotNull("ConnectivityActionReceiver didn't find NetworkInfo", networkInfo);
- int networkType = networkInfo.getType();
- State networkState = networkInfo.getState();
- Log.i(TAG, "Network type: " + networkType + " state: " + networkState);
- if (networkType == mNetworkType && networkInfo.getState() == mNetState) {
- mReceiveLatch.countDown();
- }
- }
-
- public boolean waitForState() throws InterruptedException {
- return mReceiveLatch.await(30, TimeUnit.SECONDS);
- }
- }
-
- /**
- * Callback used in testRegisterNetworkCallback that allows caller to block on
- * {@code onAvailable}.
- */
- private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
- private final CountDownLatch mAvailableLatch = new CountDownLatch(1);
- private final CountDownLatch mLostLatch = new CountDownLatch(1);
- private final CountDownLatch mUnavailableLatch = new CountDownLatch(1);
-
- 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;
- }
-
- public boolean waitForUnavailable() throws InterruptedException {
- return mUnavailableLatch.await(2, TimeUnit.SECONDS);
- }
-
-
- @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();
- }
-
- @Override
- public void onUnavailable() {
- mUnavailableLatch.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. */
@AppModeFull(reason = "CHANGE_NETWORK_STATE permission can't be granted to instant apps")
public void testRestrictedNetworks() {
@@ -1151,7 +890,7 @@
if (!isKeepaliveSupported()) return;
final Network network = ensureWifiConnected();
- final byte[] requestBytes = HTTP_REQUEST.getBytes("UTF-8");
+ final byte[] requestBytes = CtsNetUtils.HTTP_REQUEST.getBytes("UTF-8");
// So far only ipv4 tcp keepalive offload is supported.
// TODO: add test case for ipv6 tcp keepalive offload when it is supported.
try (Socket s = getConnectedSocket(network, TEST_HOST, HTTP_PORT,
diff --git a/tests/cts/net/util/Android.bp b/tests/cts/net/util/Android.bp
new file mode 100644
index 0000000..1f94613
--- /dev/null
+++ b/tests/cts/net/util/Android.bp
@@ -0,0 +1,25 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Common utilities for cts net tests.
+java_library {
+ name: "cts-net-utils",
+ srcs: ["java/**/*.java", "java/**/*.kt"],
+ static_libs: [
+ "compatibility-device-util-axt",
+ "junit",
+ ],
+}
\ No newline at end of file
diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
new file mode 100644
index 0000000..e19d2ba
--- /dev/null
+++ b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.cts.util;
+
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
+import android.net.NetworkRequest;
+import android.net.wifi.WifiManager;
+import android.system.Os;
+import android.system.OsConstants;
+import android.util.Log;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public final class CtsNetUtils {
+ private static final String TAG = CtsNetUtils.class.getSimpleName();
+ private static final int DURATION = 10000;
+ private static final int SOCKET_TIMEOUT_MS = 2000;
+
+ public static final int HTTP_PORT = 80;
+ public static final String TEST_HOST = "connectivitycheck.gstatic.com";
+ public 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.
+ public static final String NETWORK_CALLBACK_ACTION =
+ "ConnectivityManagerTest.NetworkCallbackAction";
+
+ private Context mContext;
+ private ConnectivityManager mCm;
+ private WifiManager mWifiManager;
+ private TestNetworkCallback mCellNetworkCallback;
+
+ public CtsNetUtils(Context context) {
+ mContext = context;
+ mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ }
+
+ // Toggle WiFi twice, leaving it in the state it started in
+ public void toggleWifi() {
+ if (mWifiManager.isWifiEnabled()) {
+ Network wifiNetwork = getWifiNetwork();
+ disconnectFromWifi(wifiNetwork);
+ connectToWifi();
+ } else {
+ connectToWifi();
+ Network wifiNetwork = getWifiNetwork();
+ disconnectFromWifi(wifiNetwork);
+ }
+ }
+
+ /** Enable WiFi and wait for it to become connected to a network. */
+ public Network connectToWifi() {
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
+ Network wifiNetwork = null;
+
+ ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
+ mCm, ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED);
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ mContext.registerReceiver(receiver, filter);
+
+ boolean connected = false;
+ try {
+ SystemUtil.runShellCommand("svc wifi enable");
+ // 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;
+ }
+
+ /** Disable WiFi and wait for it to become disconnected from the network. */
+ public void disconnectFromWifi(Network wifiNetworkToCheck) {
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
+ Network lostWifiNetwork = null;
+
+ ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
+ mCm, 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 {
+ SystemUtil.runShellCommand("svc wifi disable");
+ // 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());
+ }
+ }
+ }
+
+ public 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;
+ }
+
+ public Network connectToCell() throws InterruptedException {
+ if (cellConnectAttempted()) {
+ throw new IllegalStateException("Already connected");
+ }
+ NetworkRequest cellRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .build();
+ mCellNetworkCallback = new TestNetworkCallback();
+ mCm.requestNetwork(cellRequest, mCellNetworkCallback);
+ final Network cellNetwork = mCellNetworkCallback.waitForAvailable();
+ assertNotNull("Cell network not available. " +
+ "Please ensure the device has working mobile data.", cellNetwork);
+ return cellNetwork;
+ }
+
+ public void disconnectFromCell() {
+ if (!cellConnectAttempted()) {
+ throw new IllegalStateException("Cell connection not attempted");
+ }
+ mCm.unregisterNetworkCallback(mCellNetworkCallback);
+ mCellNetworkCallback = null;
+ }
+
+ public boolean cellConnectAttempted() {
+ return mCellNetworkCallback != null;
+ }
+
+ private NetworkRequest makeWifiNetworkRequest() {
+ return new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .build();
+ }
+
+ 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"));
+ }
+
+ 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;
+ }
+
+ /**
+ * Receiver that captures the last connectivity change's network type and state. Recognizes
+ * both {@code CONNECTIVITY_ACTION} and {@code NETWORK_CALLBACK_ACTION} intents.
+ */
+ public static class ConnectivityActionReceiver extends BroadcastReceiver {
+
+ private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
+
+ private final int mNetworkType;
+ private final NetworkInfo.State mNetState;
+ private final ConnectivityManager mCm;
+
+ public ConnectivityActionReceiver(ConnectivityManager cm, int networkType,
+ NetworkInfo.State netState) {
+ this.mCm = cm;
+ mNetworkType = networkType;
+ mNetState = netState;
+ }
+
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ NetworkInfo networkInfo = null;
+
+ // When receiving ConnectivityManager.CONNECTIVITY_ACTION, the NetworkInfo parcelable
+ // is stored in EXTRA_NETWORK_INFO. With a NETWORK_CALLBACK_ACTION, the Network is
+ // sent in EXTRA_NETWORK and we need to ask the ConnectivityManager for the NetworkInfo.
+ if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
+ networkInfo = intent.getExtras()
+ .getParcelable(ConnectivityManager.EXTRA_NETWORK_INFO);
+ assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK_INFO",
+ networkInfo);
+ } else if (NETWORK_CALLBACK_ACTION.equals(action)) {
+ Network network = intent.getExtras()
+ .getParcelable(ConnectivityManager.EXTRA_NETWORK);
+ assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK", network);
+ networkInfo = this.mCm.getNetworkInfo(network);
+ if (networkInfo == null) {
+ // When disconnecting, it seems like we get an intent sent with an invalid
+ // Network; that is, by the time we call ConnectivityManager.getNetworkInfo(),
+ // it is invalid. Ignore these.
+ Log.i(TAG, "ConnectivityActionReceiver NETWORK_CALLBACK_ACTION ignoring "
+ + "invalid network");
+ return;
+ }
+ } else {
+ fail("ConnectivityActionReceiver received unxpected intent action: " + action);
+ }
+
+ assertNotNull("ConnectivityActionReceiver didn't find NetworkInfo", networkInfo);
+ int networkType = networkInfo.getType();
+ State networkState = networkInfo.getState();
+ Log.i(TAG, "Network type: " + networkType + " state: " + networkState);
+ if (networkType == mNetworkType && networkInfo.getState() == mNetState) {
+ mReceiveLatch.countDown();
+ }
+ }
+
+ public boolean waitForState() throws InterruptedException {
+ return mReceiveLatch.await(30, TimeUnit.SECONDS);
+ }
+ }
+
+ /**
+ * Callback used in testRegisterNetworkCallback that allows caller to block on
+ * {@code onAvailable}.
+ */
+ public static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
+ private final CountDownLatch mAvailableLatch = new CountDownLatch(1);
+ private final CountDownLatch mLostLatch = new CountDownLatch(1);
+ private final CountDownLatch mUnavailableLatch = new CountDownLatch(1);
+
+ 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;
+ }
+
+ public boolean waitForUnavailable() throws InterruptedException {
+ return mUnavailableLatch.await(2, TimeUnit.SECONDS);
+ }
+
+
+ @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();
+ }
+
+ @Override
+ public void onUnavailable() {
+ mUnavailableLatch.countDown();
+ }
+ }
+}