Merge "Auto-configure wifi on virtual devices" into rvc-dev am: bd340d8912

Original change: https://googleplex-android-review.googlesource.com/c/platform/cts/+/11734678

Change-Id: Icacfe4c55686bdc1d6288ae19b797c99afc1d15d
This commit is contained in:
Remi NGUYEN VAN
2020-07-16 13:40:17 +00:00
committed by Automerger Merge Worker

View File

@@ -21,6 +21,9 @@ import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION;
import static com.android.compatibility.common.util.ShellIdentityUtils.invokeWithShellPermissions;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
@@ -44,6 +47,7 @@ import android.net.NetworkInfo;
import android.net.NetworkInfo.State; import android.net.NetworkInfo.State;
import android.net.NetworkRequest; import android.net.NetworkRequest;
import android.net.TestNetworkManager; import android.net.TestNetworkManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
@@ -58,13 +62,21 @@ import android.util.Log;
import com.android.compatibility.common.util.SystemUtil; import com.android.compatibility.common.util.SystemUtil;
import junit.framework.AssertionFailedError;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public final class CtsNetUtils { public final class CtsNetUtils {
private static final String TAG = CtsNetUtils.class.getSimpleName(); private static final String TAG = CtsNetUtils.class.getSimpleName();
@@ -72,7 +84,8 @@ public final class CtsNetUtils {
private static final int SOCKET_TIMEOUT_MS = 2000; private static final int SOCKET_TIMEOUT_MS = 2000;
private static final int PRIVATE_DNS_PROBE_MS = 1_000; private static final int PRIVATE_DNS_PROBE_MS = 1_000;
public static final int PRIVATE_DNS_SETTING_TIMEOUT_MS = 6_000; private static final int PRIVATE_DNS_SETTING_TIMEOUT_MS = 6_000;
private static final int CONNECTIVITY_CHANGE_TIMEOUT_SECS = 30;
public static final int HTTP_PORT = 80; public static final int HTTP_PORT = 80;
public static final String TEST_HOST = "connectivitycheck.gstatic.com"; public static final String TEST_HOST = "connectivitycheck.gstatic.com";
public static final String HTTP_REQUEST = public static final String HTTP_REQUEST =
@@ -170,8 +183,8 @@ public final class CtsNetUtils {
/** /**
* Enable WiFi and wait for it to become connected to a network. * Enable WiFi and wait for it to become connected to a network.
* *
* A network is considered connected when a {@link NetworkCallback#onAvailable(Network)} * A network is considered connected when a {@link NetworkRequest} with TRANSPORT_WIFI
* callback is received. * receives a {@link NetworkCallback#onAvailable(Network)} callback.
*/ */
public Network ensureWifiConnected() { public Network ensureWifiConnected() {
return connectToWifi(false /* expectLegacyBroadcast */); return connectToWifi(false /* expectLegacyBroadcast */);
@@ -202,8 +215,18 @@ public final class CtsNetUtils {
try { try {
clearWifiBlacklist(); clearWifiBlacklist();
SystemUtil.runShellCommand("svc wifi enable"); SystemUtil.runShellCommand("svc wifi enable");
SystemUtil.runWithShellPermissionIdentity(() -> mWifiManager.reconnect(), final WifiConfiguration config = maybeAddVirtualWifiConfiguration();
NETWORK_SETTINGS); if (config == null) {
// TODO: this may not clear the BSSID blacklist, as opposed to
// mWifiManager.connect(config)
SystemUtil.runWithShellPermissionIdentity(() -> mWifiManager.reconnect(),
NETWORK_SETTINGS);
} else {
// When running CTS, devices are expected to have wifi networks pre-configured.
// This condition is only hit on virtual devices.
SystemUtil.runWithShellPermissionIdentity(
() -> mWifiManager.connect(config, null /* listener */), NETWORK_SETTINGS);
}
// 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, wifiNetwork); assertNotNull(err, wifiNetwork);
@@ -219,6 +242,68 @@ public final class CtsNetUtils {
return wifiNetwork; return wifiNetwork;
} }
private WifiConfiguration maybeAddVirtualWifiConfiguration() {
final List<WifiConfiguration> configs = invokeWithShellPermissions(
mWifiManager::getConfiguredNetworks);
// If no network is configured, add a config for virtual access points if applicable
if (configs.size() == 0) {
final List<ScanResult> scanResults = getWifiScanResults();
final WifiConfiguration virtualConfig = maybeConfigureVirtualNetwork(scanResults);
assertNotNull("The device has no configured wifi network", virtualConfig);
return virtualConfig;
}
// No need to add a configuration: there is already one
return null;
}
private List<ScanResult> getWifiScanResults() {
final CompletableFuture<List<ScanResult>> scanResultsFuture = new CompletableFuture<>();
SystemUtil.runWithShellPermissionIdentity(() -> {
final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
scanResultsFuture.complete(mWifiManager.getScanResults());
}
};
mContext.registerReceiver(receiver, new IntentFilter(SCAN_RESULTS_AVAILABLE_ACTION));
mWifiManager.startScan();
});
try {
return scanResultsFuture.get(CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
throw new AssertionFailedError("Wifi scan results not received within timeout");
}
}
/**
* If a virtual wifi network is detected, add a configuration for that network.
* TODO(b/158150376): have the test infrastructure add virtual wifi networks when appropriate.
*/
private WifiConfiguration maybeConfigureVirtualNetwork(List<ScanResult> scanResults) {
// Virtual wifi networks used on the emulator and cloud testing infrastructure
final List<String> virtualSsids = Arrays.asList("VirtWifi", "AndroidWifi");
Log.d(TAG, "Wifi scan results: " + scanResults);
final ScanResult virtualScanResult = scanResults.stream().filter(
s -> virtualSsids.contains(s.SSID)).findFirst().orElse(null);
// Only add the virtual configuration if the virtual AP is detected in scans
if (virtualScanResult == null) return null;
final WifiConfiguration virtualConfig = new WifiConfiguration();
// ASCII SSIDs need to be surrounded by double quotes
virtualConfig.SSID = "\"" + virtualScanResult.SSID + "\"";
virtualConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
SystemUtil.runWithShellPermissionIdentity(() -> {
final int networkId = mWifiManager.addNetwork(virtualConfig);
assertTrue(networkId >= 0);
assertTrue(mWifiManager.enableNetwork(networkId, false /* attemptConnect */));
});
return virtualConfig;
}
/** /**
* Re-enable wifi networks that were blacklisted, typically because no internet connection was * Re-enable wifi networks that were blacklisted, 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
@@ -226,8 +311,8 @@ public final class CtsNetUtils {
*/ */
private void clearWifiBlacklist() { private void clearWifiBlacklist() {
SystemUtil.runWithShellPermissionIdentity(() -> { SystemUtil.runWithShellPermissionIdentity(() -> {
for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) { for (WifiConfiguration cfg : mWifiManager.getConfiguredNetworks()) {
mWifiManager.enableNetwork(config.networkId, false /* attemptConnect */); assertTrue(mWifiManager.enableNetwork(cfg.networkId, false /* attemptConnect */));
} }
}); });
} }
@@ -533,7 +618,7 @@ public final class CtsNetUtils {
} }
public boolean waitForState() throws InterruptedException { public boolean waitForState() throws InterruptedException {
return mReceiveLatch.await(30, TimeUnit.SECONDS); return mReceiveLatch.await(CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS);
} }
} }
@@ -550,11 +635,13 @@ public final class CtsNetUtils {
public Network lastLostNetwork; public Network lastLostNetwork;
public Network waitForAvailable() throws InterruptedException { public Network waitForAvailable() throws InterruptedException {
return mAvailableLatch.await(30, TimeUnit.SECONDS) ? currentNetwork : null; return mAvailableLatch.await(CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS)
? currentNetwork : null;
} }
public Network waitForLost() throws InterruptedException { public Network waitForLost() throws InterruptedException {
return mLostLatch.await(30, TimeUnit.SECONDS) ? lastLostNetwork : null; return mLostLatch.await(CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS)
? lastLostNetwork : null;
} }
public boolean waitForUnavailable() throws InterruptedException { public boolean waitForUnavailable() throws InterruptedException {