Merge "Auto-configure wifi on virtual devices" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
bd340d8912
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user