Merge changes I99ce72bd,I5a11a802 am: 527ffb6f0c am: 3499d73016

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1756971

Change-Id: Ic26bab1331de18f8b362849e275f986d0b7fa97e
This commit is contained in:
Remi NGUYEN VAN
2021-07-07 03:32:44 +00:00
committed by Automerger Merge Worker

View File

@@ -28,7 +28,6 @@ import static com.android.testutils.TestPermissionUtil.runAsShell;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@@ -56,6 +55,7 @@ import android.net.wifi.WifiManager;
import android.os.Binder; import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.os.SystemClock;
import android.system.Os; import android.system.Os;
import android.system.OsConstants; import android.system.OsConstants;
import android.text.TextUtils; import android.text.TextUtils;
@@ -73,11 +73,13 @@ import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
public final class CtsNetUtils { public final class CtsNetUtils {
private static final String TAG = CtsNetUtils.class.getSimpleName(); private static final String TAG = CtsNetUtils.class.getSimpleName();
@@ -86,6 +88,13 @@ public final class CtsNetUtils {
private static final int PRIVATE_DNS_SETTING_TIMEOUT_MS = 10_000; private static final int PRIVATE_DNS_SETTING_TIMEOUT_MS = 10_000;
private static final int CONNECTIVITY_CHANGE_TIMEOUT_SECS = 30; private static final int CONNECTIVITY_CHANGE_TIMEOUT_SECS = 30;
private static final int MAX_WIFI_CONNECT_RETRIES = 10;
private static final int WIFI_CONNECT_INTERVAL_MS = 500;
// Constants used by WifiManager.ActionListener#onFailure. Although onFailure is SystemApi,
// the error code constants are not (they probably should be ?)
private static final int WIFI_ERROR_IN_PROGRESS = 1;
private static final int WIFI_ERROR_BUSY = 2;
private static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; private static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic";
private static final String PRIVATE_DNS_MODE_STRICT = "hostname"; private static final String PRIVATE_DNS_MODE_STRICT = "hostname";
public static final int HTTP_PORT = 80; public static final int HTTP_PORT = 80;
@@ -211,32 +220,21 @@ public final class CtsNetUtils {
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mContext.registerReceiver(receiver, filter); mContext.registerReceiver(receiver, filter);
boolean connected = false;
final String err = "Wifi must be configured to connect to an access point for this test";
try { try {
clearWifiBlacklist(); // Clear the wifi config blocklist (not the BSSID blocklist)
clearWifiBlocklist();
SystemUtil.runShellCommand("svc wifi enable"); SystemUtil.runShellCommand("svc wifi enable");
final WifiConfiguration config = maybeAddVirtualWifiConfiguration(); final WifiConfiguration config = getOrCreateWifiConfiguration();
if (config == null) { connectToWifiConfig(config);
// TODO: this may not clear the BSSID blacklist, as opposed to
// mWifiManager.connect(config)
assertTrue("Error reconnecting wifi", runAsShell(NETWORK_SETTINGS,
mWifiManager::reconnect));
} else {
// When running CTS, devices are expected to have wifi networks pre-configured.
// This condition is only hit on virtual devices.
final Integer error = runAsShell(NETWORK_SETTINGS, () -> {
final ConnectWifiListener listener = new ConnectWifiListener();
mWifiManager.connect(config, listener);
return listener.connectFuture.get(
CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS);
});
assertNull("Error connecting to wifi: " + error, error);
}
// Ensure we get an onAvailable callback and possibly a CONNECTIVITY_ACTION. // Ensure we get an onAvailable callback and possibly a CONNECTIVITY_ACTION.
wifiNetwork = callback.waitForAvailable(); wifiNetwork = callback.waitForAvailable();
assertNotNull(err + ": onAvailable callback not received", wifiNetwork); assertNotNull("onAvailable callback not received after connecting to " + config.SSID,
connected = !expectLegacyBroadcast || receiver.waitForState(); wifiNetwork);
if (expectLegacyBroadcast) {
assertTrue("CONNECTIVITY_ACTION not received after connecting to " + config.SSID,
receiver.waitForState());
}
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
fail("connectToWifi was interrupted"); fail("connectToWifi was interrupted");
} finally { } finally {
@@ -244,10 +242,30 @@ public final class CtsNetUtils {
mContext.unregisterReceiver(receiver); mContext.unregisterReceiver(receiver);
} }
assertTrue(err + ": CONNECTIVITY_ACTION not received", connected);
return wifiNetwork; return wifiNetwork;
} }
private void connectToWifiConfig(WifiConfiguration config) {
for (int i = 0; i < MAX_WIFI_CONNECT_RETRIES; i++) {
final Integer error = runAsShell(NETWORK_SETTINGS, () -> {
final ConnectWifiListener listener = new ConnectWifiListener();
mWifiManager.connect(config, listener);
return listener.connectFuture.get(
CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS);
});
if (error == null) return;
// Only retry for IN_PROGRESS and BUSY
if (error != WIFI_ERROR_IN_PROGRESS && error != WIFI_ERROR_BUSY) {
fail("Failed to connect to " + config.SSID + ": " + error);
}
Log.w(TAG, "connect failed with " + error + "; waiting before retry");
SystemClock.sleep(WIFI_CONNECT_INTERVAL_MS);
}
}
private static class ConnectWifiListener implements WifiManager.ActionListener { private static class ConnectWifiListener implements WifiManager.ActionListener {
/** /**
* Future completed when the connect process ends. Provides the error code or null if none. * Future completed when the connect process ends. Provides the error code or null if none.
@@ -264,7 +282,7 @@ public final class CtsNetUtils {
} }
} }
private WifiConfiguration maybeAddVirtualWifiConfiguration() { private WifiConfiguration getOrCreateWifiConfiguration() {
final List<WifiConfiguration> configs = runAsShell(NETWORK_SETTINGS, final List<WifiConfiguration> configs = runAsShell(NETWORK_SETTINGS,
mWifiManager::getConfiguredNetworks); mWifiManager::getConfiguredNetworks);
// If no network is configured, add a config for virtual access points if applicable // If no network is configured, add a config for virtual access points if applicable
@@ -275,8 +293,24 @@ public final class CtsNetUtils {
return virtualConfig; return virtualConfig;
} }
// No need to add a configuration: there is already one // No need to add a configuration: there is already one.
return null; if (configs.size() > 1) {
// For convenience in case of local testing on devices with multiple saved configs,
// prefer the first configuration that is in range.
// In actual tests, there should only be one configuration, and it should be usable as
// assumed by WifiManagerTest.testConnect.
Log.w(TAG, "Multiple wifi configurations found: "
+ configs.stream().map(c -> c.SSID).collect(Collectors.joining(", ")));
final List<ScanResult> scanResultsList = getWifiScanResults();
Log.i(TAG, "Scan results: " + scanResultsList.stream().map(c ->
c.SSID + " (" + c.level + ")").collect(Collectors.joining(", ")));
final Set<String> scanResults = scanResultsList.stream().map(
s -> "\"" + s.SSID + "\"").collect(Collectors.toSet());
return configs.stream().filter(c -> scanResults.contains(c.SSID))
.findFirst().orElse(configs.get(0));
}
return configs.get(0);
} }
private List<ScanResult> getWifiScanResults() { private List<ScanResult> getWifiScanResults() {
@@ -327,11 +361,11 @@ public final class CtsNetUtils {
} }
/** /**
* Re-enable wifi networks that were blacklisted, typically because no internet connection was * Re-enable wifi networks that were blocklisted, typically because no internet connection was
* detected the last time they were connected. This is necessary to make sure wifi can reconnect * detected the last time they were connected. This is necessary to make sure wifi can reconnect
* to them. * to them.
*/ */
private void clearWifiBlacklist() { private void clearWifiBlocklist() {
runAsShell(NETWORK_SETTINGS, ACCESS_WIFI_STATE, () -> { runAsShell(NETWORK_SETTINGS, ACCESS_WIFI_STATE, () -> {
for (WifiConfiguration cfg : mWifiManager.getConfiguredNetworks()) { for (WifiConfiguration cfg : mWifiManager.getConfiguredNetworks()) {
assertTrue(mWifiManager.enableNetwork(cfg.networkId, false /* attemptConnect */)); assertTrue(mWifiManager.enableNetwork(cfg.networkId, false /* attemptConnect */));