Merge "Merge Android Pie into master"
This commit is contained in:
@@ -14,8 +14,15 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<configuration description="Config for CTS net host test cases">
|
||||
<option name="test-suite-tag" value="cts" />
|
||||
<option name="config-descriptor:metadata" key="component" value="networking" />
|
||||
<target_preparer class="com.android.cts.net.NetPolicyTestsPreparer" />
|
||||
|
||||
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
|
||||
<option name="teardown-command" value="cmd power set-mode 0" />
|
||||
<option name="teardown-command" value="cmd battery reset" />
|
||||
</target_preparer>
|
||||
|
||||
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
|
||||
<option name="jar" value="CtsHostsideNetworkTests.jar" />
|
||||
<option name="runtime-hint" value="3m56s" />
|
||||
|
||||
@@ -23,6 +23,8 @@ LOCAL_SDK_VERSION := current
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util ctstestrunner ub-uiautomator \
|
||||
CtsHostsideNetworkTestsAidl
|
||||
|
||||
LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := CtsHostsideNetworkTestsApp
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
|
||||
|
||||
@@ -34,7 +34,7 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork
|
||||
removePowerSaveModeWhitelist(TEST_APP2_PKG);
|
||||
removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
|
||||
setAppIdle(false);
|
||||
turnBatteryOff();
|
||||
turnBatteryOn();
|
||||
|
||||
registerBroadcastReceiver();
|
||||
}
|
||||
@@ -48,7 +48,7 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork
|
||||
try {
|
||||
tearDownMeteredNetwork();
|
||||
} finally {
|
||||
turnBatteryOn();
|
||||
turnBatteryOff();
|
||||
setAppIdle(false);
|
||||
}
|
||||
}
|
||||
@@ -127,6 +127,19 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork
|
||||
assertBackgroundNetworkAccess(false);
|
||||
}
|
||||
|
||||
public void testBackgroundNetworkAccess_tempWhitelisted() throws Exception {
|
||||
if (!isSupported()) return;
|
||||
|
||||
setAppIdle(true);
|
||||
assertBackgroundNetworkAccess(false);
|
||||
|
||||
addTempPowerSaveModeWhitelist(TEST_APP2_PKG, TEMP_POWERSAVE_WHITELIST_DURATION_MS);
|
||||
assertBackgroundNetworkAccess(true);
|
||||
// Wait until the whitelist duration is expired.
|
||||
SystemClock.sleep(TEMP_POWERSAVE_WHITELIST_DURATION_MS);
|
||||
assertBackgroundNetworkAccess(false);
|
||||
}
|
||||
|
||||
public void testBackgroundNetworkAccess_disabled() throws Exception {
|
||||
if (!isSupported()) return;
|
||||
|
||||
@@ -142,9 +155,9 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork
|
||||
// Check that app is paroled when charging
|
||||
setAppIdle(true);
|
||||
assertBackgroundNetworkAccess(false);
|
||||
turnBatteryOn();
|
||||
assertBackgroundNetworkAccess(true);
|
||||
turnBatteryOff();
|
||||
assertBackgroundNetworkAccess(true);
|
||||
turnBatteryOn();
|
||||
assertBackgroundNetworkAccess(false);
|
||||
|
||||
// Check that app is restricted when not idle but power-save is on
|
||||
@@ -154,11 +167,11 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork
|
||||
assertBackgroundNetworkAccess(false);
|
||||
// Use setBatterySaverMode API to leave power-save mode instead of plugging in charger
|
||||
setBatterySaverMode(false);
|
||||
turnBatteryOn();
|
||||
turnBatteryOff();
|
||||
assertBackgroundNetworkAccess(true);
|
||||
|
||||
// And when no longer charging, it still has network access, since it's not idle
|
||||
turnBatteryOff();
|
||||
turnBatteryOn();
|
||||
assertBackgroundNetworkAccess(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,10 @@ import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED
|
||||
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
|
||||
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
|
||||
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
|
||||
import static android.os.BatteryManager.BATTERY_PLUGGED_AC;
|
||||
import static android.os.BatteryManager.BATTERY_PLUGGED_USB;
|
||||
import static android.os.BatteryManager.BATTERY_PLUGGED_WIRELESS;
|
||||
|
||||
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@@ -49,8 +53,6 @@ import android.test.InstrumentationTestCase;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.cts.net.hostside.INetworkStateObserver;
|
||||
|
||||
/**
|
||||
* Superclass for tests related to background network restrictions.
|
||||
*/
|
||||
@@ -83,11 +85,14 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
protected static final String NOTIFICATION_TYPE_ACTION_BUNDLE = "ACTION_BUNDLE";
|
||||
protected static final String NOTIFICATION_TYPE_ACTION_REMOTE_INPUT = "ACTION_REMOTE_INPUT";
|
||||
|
||||
// TODO: Update BatteryManager.BATTERY_PLUGGED_ANY as @TestApi
|
||||
public static final int BATTERY_PLUGGED_ANY =
|
||||
BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS;
|
||||
|
||||
private static final String NETWORK_STATUS_SEPARATOR = "\\|";
|
||||
private static final int SECOND_IN_MS = 1000;
|
||||
static final int NETWORK_TIMEOUT_MS = 15 * SECOND_IN_MS;
|
||||
private static final int PROCESS_STATE_FOREGROUND_SERVICE = 4;
|
||||
private static final int PROCESS_STATE_FOREGROUND_SERVICE = 3;
|
||||
private static final int PROCESS_STATE_TOP = 2;
|
||||
|
||||
private static final String KEY_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer";
|
||||
@@ -108,6 +113,8 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
|
||||
private static final String APP_NOT_FOREGROUND_ERROR = "app_not_fg";
|
||||
|
||||
protected static final long TEMP_POWERSAVE_WHITELIST_DURATION_MS = 5_000; // 5 sec
|
||||
|
||||
protected Context mContext;
|
||||
protected Instrumentation mInstrumentation;
|
||||
protected ConnectivityManager mCm;
|
||||
@@ -138,6 +145,7 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
enableLocation();
|
||||
}
|
||||
mSupported = setUpActiveNetworkMeteringState();
|
||||
setAppIdle(false);
|
||||
|
||||
Log.i(TAG, "Apps status on " + getName() + ":\n"
|
||||
+ "\ttest app: uid=" + mMyUid + ", state=" + getProcessStateByUid(mMyUid) + "\n"
|
||||
@@ -258,17 +266,21 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
|
||||
protected void assertBackgroundNetworkAccess(boolean expectAllowed) throws Exception {
|
||||
assertBackgroundState(); // Sanity check.
|
||||
assertNetworkAccess(expectAllowed);
|
||||
assertNetworkAccess(expectAllowed /* expectAvailable */, false /* needScreenOn */);
|
||||
}
|
||||
|
||||
protected void assertForegroundNetworkAccess() throws Exception {
|
||||
assertForegroundState(); // Sanity check.
|
||||
assertNetworkAccess(true);
|
||||
// We verified that app is in foreground state but if the screen turns-off while
|
||||
// verifying for network access, the app will go into background state (in case app's
|
||||
// foreground status was due to top activity). So, turn the screen on when verifying
|
||||
// network connectivity.
|
||||
assertNetworkAccess(true /* expectAvailable */, true /* needScreenOn */);
|
||||
}
|
||||
|
||||
protected void assertForegroundServiceNetworkAccess() throws Exception {
|
||||
assertForegroundServiceState(); // Sanity check.
|
||||
assertNetworkAccess(true);
|
||||
assertNetworkAccess(true /* expectAvailable */, false /* needScreenOn */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,7 +379,8 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
/**
|
||||
* Asserts whether the active network is available or not.
|
||||
*/
|
||||
private void assertNetworkAccess(boolean expectAvailable) throws Exception {
|
||||
private void assertNetworkAccess(boolean expectAvailable, boolean needScreenOn)
|
||||
throws Exception {
|
||||
final int maxTries = 5;
|
||||
String error = null;
|
||||
int timeoutMs = 500;
|
||||
@@ -385,6 +398,9 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
Log.w(TAG, "Network status didn't match for expectAvailable=" + expectAvailable
|
||||
+ " on attempt #" + i + ": " + error + "\n"
|
||||
+ "Sleeping " + timeoutMs + "ms before trying again");
|
||||
if (needScreenOn) {
|
||||
turnScreenOn();
|
||||
}
|
||||
// No sleep after the last turn
|
||||
if (i < maxTries) {
|
||||
SystemClock.sleep(timeoutMs);
|
||||
@@ -751,6 +767,12 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
+ ". Full list: " + uids);
|
||||
}
|
||||
|
||||
protected void addTempPowerSaveModeWhitelist(String packageName, long duration)
|
||||
throws Exception {
|
||||
Log.i(TAG, "Adding pkg " + packageName + " to temp-power-save-mode whitelist");
|
||||
executeShellCommand("dumpsys deviceidle tempwhitelist -d " + duration + " " + packageName);
|
||||
}
|
||||
|
||||
protected void assertPowerSaveModeWhitelist(String packageName, boolean expected)
|
||||
throws Exception {
|
||||
// TODO: currently the power-save mode is behaving like idle, but once it changes, we'll
|
||||
@@ -800,15 +822,19 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
assertPowerSaveModeExceptIdleWhitelist(packageName, false); // Sanity check
|
||||
}
|
||||
|
||||
protected void turnBatteryOff() throws Exception {
|
||||
protected void turnBatteryOn() throws Exception {
|
||||
executeSilentShellCommand("cmd battery unplug");
|
||||
executeSilentShellCommand("cmd battery set status "
|
||||
+ BatteryManager.BATTERY_STATUS_DISCHARGING);
|
||||
assertBatteryState(false);
|
||||
}
|
||||
|
||||
protected void turnBatteryOn() throws Exception {
|
||||
executeSilentShellCommand("cmd battery reset");
|
||||
protected void turnBatteryOff() throws Exception {
|
||||
executeSilentShellCommand("cmd battery set ac " + BATTERY_PLUGGED_ANY);
|
||||
executeSilentShellCommand("cmd battery set level 100");
|
||||
executeSilentShellCommand("cmd battery set status "
|
||||
+ BatteryManager.BATTERY_STATUS_CHARGING);
|
||||
assertBatteryState(true);
|
||||
|
||||
}
|
||||
|
||||
private void assertBatteryState(boolean pluggedIn) throws Exception {
|
||||
@@ -839,11 +865,11 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
protected void setBatterySaverMode(boolean enabled) throws Exception {
|
||||
Log.i(TAG, "Setting Battery Saver Mode to " + enabled);
|
||||
if (enabled) {
|
||||
turnBatteryOff();
|
||||
turnBatteryOn();
|
||||
executeSilentShellCommand("cmd power set-mode 1");
|
||||
} else {
|
||||
executeSilentShellCommand("cmd power set-mode 0");
|
||||
turnBatteryOn();
|
||||
turnBatteryOff();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -853,12 +879,12 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
|
||||
Log.i(TAG, "Setting Doze Mode to " + enabled);
|
||||
if (enabled) {
|
||||
turnBatteryOff();
|
||||
turnBatteryOn();
|
||||
turnScreenOff();
|
||||
executeShellCommand("dumpsys deviceidle force-idle deep");
|
||||
} else {
|
||||
turnScreenOn();
|
||||
turnBatteryOn();
|
||||
turnBatteryOff();
|
||||
executeShellCommand("dumpsys deviceidle unforce");
|
||||
}
|
||||
// Sanity check.
|
||||
@@ -1004,7 +1030,8 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
private Intent getIntentForComponent(int type) {
|
||||
final Intent intent = new Intent();
|
||||
if (type == TYPE_COMPONENT_ACTIVTIY) {
|
||||
intent.setComponent(new ComponentName(TEST_APP2_PKG, TEST_APP2_ACTIVITY_CLASS));
|
||||
intent.setComponent(new ComponentName(TEST_APP2_PKG, TEST_APP2_ACTIVITY_CLASS))
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
} else if (type == TYPE_COMPONENT_FOREGROUND_SERVICE) {
|
||||
intent.setComponent(new ComponentName(TEST_APP2_PKG, TEST_APP2_SERVICE_CLASS))
|
||||
.setFlags(1);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.cts.net.hostside;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
@@ -56,18 +57,22 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() throws Exception {
|
||||
if (!isDozeModeEnabled()) {
|
||||
Log.i(TAG, "Skipping " + getClass() + "." + getName()
|
||||
+ "() because device does not support Doze Mode");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests all DS ON and BS ON scenarios from network-policy-restrictions.md on metered networks.
|
||||
*/
|
||||
public void testDataAndBatterySaverModes_meteredNetwork() throws Exception {
|
||||
if (!isSupported()) return;
|
||||
|
||||
if (!isDozeModeEnabled()) {
|
||||
Log.w(TAG, "testDataAndBatterySaverModes_meteredNetwork() skipped because "
|
||||
+ "device does not support Doze Mode");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i(TAG, "testDataAndBatterySaverModes_meteredNetwork() tests");
|
||||
if (!setMeteredNetwork()) {
|
||||
Log.w(TAG, "testDataAndBatterySaverModes_meteredNetwork() skipped because "
|
||||
@@ -138,12 +143,6 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
|
||||
public void testDataAndBatterySaverModes_nonMeteredNetwork() throws Exception {
|
||||
if (!isSupported()) return;
|
||||
|
||||
if (!isDozeModeEnabled()) {
|
||||
Log.w(TAG, "testDataAndBatterySaverModes_nonMeteredNetwork() skipped because "
|
||||
+ "device does not support Doze Mode");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!setUnmeteredNetwork()) {
|
||||
Log.w(TAG, "testDataAndBatterySaverModes_nonMeteredNetwork() skipped because network"
|
||||
+ " is metered");
|
||||
@@ -210,11 +209,6 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
|
||||
if (!isSupported()) {
|
||||
return;
|
||||
}
|
||||
if (!isDozeModeEnabled()) {
|
||||
Log.i(TAG, "Skipping " + getClass() + "." + getName()
|
||||
+ "() because device does not support Doze Mode");
|
||||
return;
|
||||
}
|
||||
|
||||
setBatterySaverMode(true);
|
||||
setDozeMode(true);
|
||||
@@ -245,11 +239,6 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
|
||||
if (!isSupported()) {
|
||||
return;
|
||||
}
|
||||
if (!isDozeModeEnabled()) {
|
||||
Log.i(TAG, "Skipping " + getClass() + "." + getName()
|
||||
+ "() because device does not support Doze Mode");
|
||||
return;
|
||||
}
|
||||
|
||||
setDozeMode(true);
|
||||
setAppIdle(true);
|
||||
@@ -271,4 +260,50 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
|
||||
setDozeMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAppIdleAndDoze_tempPowerSaveWhitelists() throws Exception {
|
||||
if (!isSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setDozeMode(true);
|
||||
setAppIdle(true);
|
||||
|
||||
try {
|
||||
assertBackgroundNetworkAccess(false);
|
||||
|
||||
addTempPowerSaveModeWhitelist(TEST_APP2_PKG, TEMP_POWERSAVE_WHITELIST_DURATION_MS);
|
||||
assertBackgroundNetworkAccess(true);
|
||||
|
||||
// Wait until the whitelist duration is expired.
|
||||
SystemClock.sleep(TEMP_POWERSAVE_WHITELIST_DURATION_MS);
|
||||
assertBackgroundNetworkAccess(false);
|
||||
} finally {
|
||||
setAppIdle(false);
|
||||
setDozeMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAppIdleAndBatterySaver_tempPowerSaveWhitelists() throws Exception {
|
||||
if (!isSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setBatterySaverMode(true);
|
||||
setAppIdle(true);
|
||||
|
||||
try {
|
||||
assertBackgroundNetworkAccess(false);
|
||||
|
||||
addTempPowerSaveModeWhitelist(TEST_APP2_PKG, TEMP_POWERSAVE_WHITELIST_DURATION_MS);
|
||||
assertBackgroundNetworkAccess(true);
|
||||
|
||||
// Wait until the whitelist duration is expired.
|
||||
SystemClock.sleep(TEMP_POWERSAVE_WHITELIST_DURATION_MS);
|
||||
assertBackgroundNetworkAccess(false);
|
||||
} finally {
|
||||
setAppIdle(false);
|
||||
setBatterySaverMode(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
package="com.android.cts.net.hostside.app2" >
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<!--
|
||||
@@ -33,7 +34,7 @@
|
||||
This application also provides a service, RemoteSocketFactoryService, that the test app can
|
||||
use to open sockets to remote hosts as a different user ID.
|
||||
-->
|
||||
<application>
|
||||
<application android:usesCleartextTraffic="true">
|
||||
<activity android:name=".MyActivity" android:exported="true"/>
|
||||
<service android:name=".MyService" android:exported="true"/>
|
||||
<service android:name=".MyForegroundService" android:exported="true"/>
|
||||
|
||||
@@ -19,13 +19,13 @@ package com.android.cts.net;
|
||||
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
|
||||
import com.android.ddmlib.Log;
|
||||
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
|
||||
import com.android.ddmlib.testrunner.TestIdentifier;
|
||||
import com.android.ddmlib.testrunner.TestResult;
|
||||
import com.android.ddmlib.testrunner.TestResult.TestStatus;
|
||||
import com.android.ddmlib.testrunner.TestRunResult;
|
||||
import com.android.tradefed.build.IBuildInfo;
|
||||
import com.android.tradefed.device.DeviceNotAvailableException;
|
||||
import com.android.tradefed.result.CollectingTestListener;
|
||||
import com.android.tradefed.result.TestDescription;
|
||||
import com.android.tradefed.result.TestResult;
|
||||
import com.android.tradefed.result.TestRunResult;
|
||||
import com.android.tradefed.testtype.DeviceTestCase;
|
||||
import com.android.tradefed.testtype.IAbi;
|
||||
import com.android.tradefed.testtype.IAbiReceiver;
|
||||
@@ -150,7 +150,7 @@ abstract class HostsideNetworkTestCase extends DeviceTestCase implements IAbiRec
|
||||
if (result.hasFailedTests()) {
|
||||
// build a meaningful error message
|
||||
StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
|
||||
for (Map.Entry<TestIdentifier, TestResult> resultEntry :
|
||||
for (Map.Entry<TestDescription, TestResult> resultEntry :
|
||||
result.getTestResults().entrySet()) {
|
||||
if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
|
||||
errorBuilder.append(resultEntry.getKey().toString());
|
||||
|
||||
@@ -146,6 +146,11 @@ public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestC
|
||||
"testBackgroundNetworkAccess_whitelisted");
|
||||
}
|
||||
|
||||
public void testAppIdleMetered_tempWhitelisted() throws Exception {
|
||||
runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleMeteredTest",
|
||||
"testBackgroundNetworkAccess_tempWhitelisted");
|
||||
}
|
||||
|
||||
public void testAppIdleMetered_enabled() throws Exception {
|
||||
runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleMeteredTest",
|
||||
"testBackgroundNetworkAccess_enabled");
|
||||
@@ -166,6 +171,11 @@ public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestC
|
||||
"testBackgroundNetworkAccess_whitelisted");
|
||||
}
|
||||
|
||||
public void testAppIdleNonMetered_tempWhitelisted() throws Exception {
|
||||
runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest",
|
||||
"testBackgroundNetworkAccess_tempWhitelisted");
|
||||
}
|
||||
|
||||
public void testAppIdleNonMetered_enabled() throws Exception {
|
||||
runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest",
|
||||
"testBackgroundNetworkAccess_enabled");
|
||||
@@ -261,6 +271,16 @@ public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestC
|
||||
"testDozeAndAppIdle_powerSaveWhitelists");
|
||||
}
|
||||
|
||||
public void testAppIdleAndDoze_tempPowerSaveWhitelists() throws Exception {
|
||||
runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest",
|
||||
"testAppIdleAndDoze_tempPowerSaveWhitelists");
|
||||
}
|
||||
|
||||
public void testAppIdleAndBatterySaver_tempPowerSaveWhitelists() throws Exception {
|
||||
runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest",
|
||||
"testAppIdleAndBatterySaver_tempPowerSaveWhitelists");
|
||||
}
|
||||
|
||||
/*******************
|
||||
* Helper methods. *
|
||||
*******************/
|
||||
|
||||
@@ -25,50 +25,38 @@ import com.android.tradefed.targetprep.ITargetPreparer;
|
||||
|
||||
public class NetPolicyTestsPreparer implements ITargetPreparer, ITargetCleaner {
|
||||
private final static String KEY_PAROLE_DURATION = "parole_duration";
|
||||
private final static String DESIRED_PAROLE_DURATION = "0";
|
||||
private final static int DESIRED_PAROLE_DURATION = 0;
|
||||
private final static String KEY_STABLE_CHARGING_THRESHOLD = "stable_charging_threshold";
|
||||
private final static int DESIRED_STABLE_CHARGING_THRESHOLD = 0;
|
||||
|
||||
private boolean mAppIdleConstsUpdated;
|
||||
private ITestDevice mDevice;
|
||||
private String mOriginalAppIdleConsts;
|
||||
|
||||
@Override
|
||||
public void setUp(ITestDevice device, IBuildInfo buildInfo) throws DeviceNotAvailableException {
|
||||
updateParoleDuration(device);
|
||||
mDevice = device;
|
||||
mOriginalAppIdleConsts = getAppIdleConstants();
|
||||
setAppIdleConstants(KEY_PAROLE_DURATION + "=" + DESIRED_PAROLE_DURATION + ","
|
||||
+ KEY_STABLE_CHARGING_THRESHOLD + "=" + DESIRED_STABLE_CHARGING_THRESHOLD);
|
||||
LogUtil.CLog.d("Original app_idle_constants: " + mOriginalAppIdleConsts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable throwable)
|
||||
throws DeviceNotAvailableException {
|
||||
if (mAppIdleConstsUpdated) {
|
||||
executeCmd(device, "settings put global app_idle_constants " + mOriginalAppIdleConsts);
|
||||
}
|
||||
setAppIdleConstants(mOriginalAppIdleConsts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates parole_duration with the desired value.
|
||||
*/
|
||||
private void updateParoleDuration(ITestDevice device) throws DeviceNotAvailableException {
|
||||
mOriginalAppIdleConsts = executeCmd(device, "settings get global app_idle_constants");
|
||||
String newAppIdleConstants;
|
||||
final String newConstant = KEY_PAROLE_DURATION + "=" + DESIRED_PAROLE_DURATION;
|
||||
if (mOriginalAppIdleConsts == null || "null".equals(mOriginalAppIdleConsts)) {
|
||||
// app_idle_constants is initially empty, so just assign the desired value.
|
||||
newAppIdleConstants = newConstant;
|
||||
} else if (mOriginalAppIdleConsts.contains(KEY_PAROLE_DURATION)) {
|
||||
// app_idle_constants contains parole_duration, so replace it with the desired value.
|
||||
newAppIdleConstants = mOriginalAppIdleConsts.replaceAll(
|
||||
KEY_PAROLE_DURATION + "=\\d+", newConstant);
|
||||
} else {
|
||||
// app_idle_constants didn't have parole_duration, so append the desired value.
|
||||
newAppIdleConstants = mOriginalAppIdleConsts + "," + newConstant;
|
||||
}
|
||||
executeCmd(device, "settings put global app_idle_constants " + newAppIdleConstants);
|
||||
mAppIdleConstsUpdated = true;
|
||||
private void setAppIdleConstants(String appIdleConstants) throws DeviceNotAvailableException {
|
||||
executeCmd("settings put global app_idle_constants " + appIdleConstants);
|
||||
}
|
||||
|
||||
private String executeCmd(ITestDevice device, String cmd)
|
||||
throws DeviceNotAvailableException {
|
||||
final String output = device.executeShellCommand(cmd).trim();
|
||||
private String getAppIdleConstants() throws DeviceNotAvailableException {
|
||||
return executeCmd("settings get global app_idle_constants");
|
||||
}
|
||||
|
||||
private String executeCmd(String cmd) throws DeviceNotAvailableException {
|
||||
final String output = mDevice.executeShellCommand(cmd).trim();
|
||||
LogUtil.CLog.d("Output for '%s': %s", cmd, output);
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,12 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
|
||||
# Include both the 32 and 64 bit versions
|
||||
LOCAL_MULTILIB := both
|
||||
|
||||
LOCAL_JAVA_LIBRARIES := voip-common conscrypt org.apache.http.legacy
|
||||
LOCAL_JAVA_LIBRARIES := \
|
||||
voip-common \
|
||||
conscrypt \
|
||||
org.apache.http.legacy \
|
||||
android.test.base.stubs \
|
||||
|
||||
|
||||
LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libnativedns_jni \
|
||||
libnativemultinetwork_jni libnativehelper_compat_libc++
|
||||
@@ -41,7 +46,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
ctstestserver \
|
||||
mockwebserver \
|
||||
junit \
|
||||
legacy-android-test
|
||||
truth-prebuilt
|
||||
|
||||
# uncomment when b/13249961 is fixed
|
||||
#LOCAL_SDK_VERSION := current
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
||||
@@ -30,7 +31,7 @@
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
|
||||
|
||||
<application>
|
||||
<application android:usesCleartextTraffic="true">
|
||||
<uses-library android:name="android.test.runner" />
|
||||
<uses-library android:name="org.apache.http.legacy" android:required="false" />
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<configuration description="Config for CTS Net test cases">
|
||||
<option name="test-suite-tag" value="cts" />
|
||||
<option name="config-descriptor:metadata" key="component" value="networking" />
|
||||
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
|
||||
<option name="cleanup-apks" value="true" />
|
||||
@@ -22,5 +23,6 @@
|
||||
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
|
||||
<option name="package" value="android.net.cts" />
|
||||
<option name="runtime-hint" value="9m4s" />
|
||||
<option name="hidden-api-checks" value="false" />
|
||||
</test>
|
||||
</configuration>
|
||||
|
||||
2
tests/cts/net/OWNERS
Normal file
2
tests/cts/net/OWNERS
Normal file
@@ -0,0 +1,2 @@
|
||||
lorenzo@google.com
|
||||
satk@google.com
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2018 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.
|
||||
*/
|
||||
-->
|
||||
<!-- This test config file is for NetworkWatchlistTest tests -->
|
||||
<watchlist-config>
|
||||
<sha256-domain>
|
||||
</sha256-domain>
|
||||
<sha256-ip>
|
||||
</sha256-ip>
|
||||
<crc32-domain>
|
||||
</crc32-domain>
|
||||
<crc32-ip>
|
||||
</crc32-ip>
|
||||
</watchlist-config>
|
||||
34
tests/cts/net/assets/network_watchlist_config_for_test.xml
Normal file
34
tests/cts/net/assets/network_watchlist_config_for_test.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2018 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.
|
||||
*/
|
||||
-->
|
||||
<!-- This test config file just contains some random hashes for testing
|
||||
ConnectivityManager.getWatchlistConfigHash() -->
|
||||
<watchlist-config>
|
||||
<sha256-domain>
|
||||
<hash>F0905DA7549614957B449034C281EF7BDEFDBC2B6E050AD1E78D6DE18FBD0D5F</hash>
|
||||
</sha256-domain>
|
||||
<sha256-ip>
|
||||
<hash>18DD41C9F2E8E4879A1575FB780514EF33CF6E1F66578C4AE7CCA31F49B9F2EC</hash>
|
||||
</sha256-ip>
|
||||
<crc32-domain>
|
||||
<hash>AAAAAAAA</hash>
|
||||
</crc32-domain>
|
||||
<crc32-ip>
|
||||
<hash>BBBBBBBB</hash>
|
||||
</crc32-ip>
|
||||
</watchlist-config>
|
||||
@@ -14,6 +14,7 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<configuration description="Config for CTS Native Network xt_qtaguid test cases">
|
||||
<option name="test-suite-tag" value="cts" />
|
||||
<option name="config-descriptor:metadata" key="component" value="networking" />
|
||||
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
|
||||
<option name="cleanup" value="true" />
|
||||
|
||||
@@ -16,9 +16,12 @@
|
||||
|
||||
package android.net.cts;
|
||||
|
||||
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
|
||||
import static android.content.pm.PackageManager.FEATURE_WIFI;
|
||||
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.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
|
||||
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
|
||||
@@ -34,6 +37,7 @@ import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.ConnectivityManager.NetworkCallback;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkConfig;
|
||||
@@ -60,10 +64,18 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.NumberFormatException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@@ -71,6 +83,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import libcore.io.Streams;
|
||||
|
||||
public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
|
||||
@@ -124,6 +137,8 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
private final HashMap<Integer, NetworkConfig> mNetworks =
|
||||
new HashMap<Integer, NetworkConfig>();
|
||||
boolean mWifiConnectAttempted;
|
||||
private TestNetworkCallback mCellNetworkCallback;
|
||||
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
@@ -158,6 +173,10 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
if (mWifiConnectAttempted) {
|
||||
disconnectFromWifi(null);
|
||||
}
|
||||
if (cellConnectAttempted()) {
|
||||
disconnectFromCell();
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,6 +283,95 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that connections can be opened on WiFi and cellphone networks,
|
||||
* and that they are made from different IP addresses.
|
||||
*/
|
||||
public void testOpenConnection() throws Exception {
|
||||
boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI)
|
||||
&& mPackageManager.hasSystemFeature(FEATURE_TELEPHONY);
|
||||
if (!canRunTest) {
|
||||
Log.i(TAG,"testOpenConnection cannot execute unless device supports both WiFi "
|
||||
+ "and a cellular connection");
|
||||
return;
|
||||
}
|
||||
|
||||
Network wifiNetwork = connectToWifi();
|
||||
Network cellNetwork = 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);
|
||||
String cellAddressString = httpGet(cellNetwork, url);
|
||||
|
||||
assertFalse(String.format("Same address '%s' on two different networks (%s, %s)",
|
||||
wifiAddressString, wifiNetwork, cellNetwork),
|
||||
wifiAddressString.equals(cellAddressString));
|
||||
|
||||
// Sanity check that the IP addresses that the requests appeared to come from
|
||||
// are actually on the respective networks.
|
||||
assertOnNetwork(wifiAddressString, wifiNetwork);
|
||||
assertOnNetwork(cellAddressString, cellNetwork);
|
||||
|
||||
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.
|
||||
*/
|
||||
private static String httpGet(Network network, URL httpUrl) throws IOException {
|
||||
HttpURLConnection connection = (HttpURLConnection) network.openConnection(httpUrl);
|
||||
try {
|
||||
InputStream inputStream = connection.getInputStream();
|
||||
return Streams.readFully(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
||||
} finally {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertOnNetwork(String adressString, Network network) throws UnknownHostException {
|
||||
InetAddress address = InetAddress.getByName(adressString);
|
||||
LinkProperties linkProperties = mCm.getLinkProperties(network);
|
||||
// To make sure that the request went out on the right network, check that
|
||||
// the IP address seen by the server is assigned to the expected network.
|
||||
// We can only do this for IPv6 addresses, because in IPv4 we will likely
|
||||
// have a private IPv4 address, and that won't match what the server sees.
|
||||
if (address instanceof Inet6Address) {
|
||||
assertContains(linkProperties.getAddresses(), address);
|
||||
}
|
||||
}
|
||||
|
||||
private static<T> void assertContains(Collection<T> collection, T element) {
|
||||
assertTrue(element + " not found in " + collection, collection.contains(element));
|
||||
}
|
||||
|
||||
private void assertStartUsingNetworkFeatureUnsupported(int networkType, String feature) {
|
||||
try {
|
||||
mCm.startUsingNetworkFeature(networkType, feature);
|
||||
@@ -342,7 +450,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
* that it would increase test coverage by much (how many devices have 3G radio but not Wifi?).
|
||||
*/
|
||||
public void testRegisterNetworkCallback() {
|
||||
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
|
||||
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
|
||||
Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi");
|
||||
return;
|
||||
}
|
||||
@@ -382,7 +490,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
* of a {@code NetworkCallback}.
|
||||
*/
|
||||
public void testRegisterNetworkCallback_withPendingIntent() {
|
||||
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
|
||||
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
|
||||
Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi");
|
||||
return;
|
||||
}
|
||||
@@ -476,7 +584,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
* Tests reporting of connectivity changed.
|
||||
*/
|
||||
public void testConnectivityChanged_manifestRequestOnly_shouldNotReceiveIntent() {
|
||||
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
|
||||
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
|
||||
Log.i(TAG, "testConnectivityChanged_manifestRequestOnly_shouldNotReceiveIntent cannot execute unless device supports WiFi");
|
||||
return;
|
||||
}
|
||||
@@ -493,7 +601,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
public void testConnectivityChanged_whenRegistered_shouldReceiveIntent() {
|
||||
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
|
||||
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
|
||||
Log.i(TAG, "testConnectivityChanged_whenRegistered_shouldReceiveIntent cannot execute unless device supports WiFi");
|
||||
return;
|
||||
}
|
||||
@@ -513,14 +621,14 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
|
||||
public void testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent()
|
||||
throws InterruptedException {
|
||||
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
|
||||
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
|
||||
Log.i(TAG, "testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent cannot execute unless device supports WiFi");
|
||||
return;
|
||||
}
|
||||
Intent startIntent = new Intent();
|
||||
startIntent.setComponent(new ComponentName("android.net.cts.appForApi23",
|
||||
"android.net.cts.appForApi23.ConnectivityListeningActivity"));
|
||||
mContext.startActivity(startIntent);
|
||||
mContext.startActivity(new Intent()
|
||||
.setComponent(new ComponentName("android.net.cts.appForApi23",
|
||||
"android.net.cts.appForApi23.ConnectivityListeningActivity"))
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
Thread.sleep(200);
|
||||
|
||||
toggleWifi();
|
||||
|
||||
@@ -19,6 +19,9 @@ package android.net.cts;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.ConnectivityManager.NetworkCallback;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.SystemClock;
|
||||
import android.test.AndroidTestCase;
|
||||
@@ -29,6 +32,8 @@ import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class DnsTest extends AndroidTestCase {
|
||||
|
||||
@@ -40,6 +45,12 @@ public class DnsTest extends AndroidTestCase {
|
||||
private static final String TAG = "DnsTest";
|
||||
private static final String PROXY_NETWORK_TYPE = "PROXY";
|
||||
|
||||
private ConnectivityManager mCm;
|
||||
|
||||
public void setUp() {
|
||||
mCm = getContext().getSystemService(ConnectivityManager.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true on success
|
||||
*/
|
||||
@@ -57,7 +68,9 @@ public class DnsTest extends AndroidTestCase {
|
||||
* Perf - measure size of first and second tier caches and their effect
|
||||
* Assert requires network permission
|
||||
*/
|
||||
public void testDnsWorks() {
|
||||
public void testDnsWorks() throws Exception {
|
||||
ensureIpv6Connectivity();
|
||||
|
||||
InetAddress addrs[] = {};
|
||||
try {
|
||||
addrs = InetAddress.getAllByName("www.google.com");
|
||||
@@ -88,11 +101,14 @@ public class DnsTest extends AndroidTestCase {
|
||||
try {
|
||||
addrs = InetAddress.getAllByName("ipv6.google.com");
|
||||
} catch (UnknownHostException e) {}
|
||||
assertTrue("[RERUN] DNS could not resolve ipv6.google.com, check the network supports IPv6",
|
||||
addrs.length != 0);
|
||||
String msg =
|
||||
"[RERUN] DNS could not resolve ipv6.google.com, check the network supports IPv6. lp=" +
|
||||
mCm.getActiveLinkProperties();
|
||||
assertTrue(msg, addrs.length != 0);
|
||||
for (InetAddress addr : addrs) {
|
||||
assertFalse ("[RERUN] ipv6.google.com returned IPv4 address: " + addr.getHostAddress() +
|
||||
", check your network's DNS server", addr instanceof Inet4Address);
|
||||
msg = "[RERUN] ipv6.google.com returned IPv4 address: " + addr.getHostAddress() +
|
||||
", check your network's DNS server. lp=" + mCm.getActiveLinkProperties();
|
||||
assertFalse (msg, addr instanceof Inet4Address);
|
||||
foundV6 |= (addr instanceof Inet6Address);
|
||||
if (DBG) Log.e(TAG, "ipv6.google.com gave " + addr.toString());
|
||||
}
|
||||
@@ -256,13 +272,35 @@ public class DnsTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
private boolean activeNetworkInfoIsProxy() {
|
||||
ConnectivityManager cm = (ConnectivityManager)
|
||||
getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo info = cm.getActiveNetworkInfo();
|
||||
NetworkInfo info = mCm.getActiveNetworkInfo();
|
||||
if (PROXY_NETWORK_TYPE.equals(info.getTypeName())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ensureIpv6Connectivity() throws InterruptedException {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
final int TIMEOUT_MS = 5_000;
|
||||
|
||||
final NetworkCallback callback = new NetworkCallback() {
|
||||
@Override
|
||||
public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
|
||||
if (lp.hasGlobalIPv6Address()) {
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
};
|
||||
mCm.registerDefaultNetworkCallback(callback);
|
||||
|
||||
String msg = "Default network did not provide IPv6 connectivity after " + TIMEOUT_MS
|
||||
+ "ms. Please connect to an IPv6-capable network. lp="
|
||||
+ mCm.getActiveLinkProperties();
|
||||
try {
|
||||
assertTrue(msg, latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||
} finally {
|
||||
mCm.unregisterNetworkCallback(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,4 +152,27 @@ public class MultinetworkApiTest extends AndroidTestCase {
|
||||
// to query on the default network.
|
||||
// assertEquals(-OsConstants.ENONET, runGetaddrinfoCheck(eNoNetHandle));
|
||||
}
|
||||
|
||||
public void testNetworkHandle() {
|
||||
// Test Network -> NetworkHandle -> Network results in the same Network.
|
||||
for (Network network : getTestableNetworks()) {
|
||||
long networkHandle = network.getNetworkHandle();
|
||||
Network newNetwork = Network.fromNetworkHandle(networkHandle);
|
||||
assertEquals(newNetwork, network);
|
||||
}
|
||||
|
||||
// Test that only obfuscated handles are allowed.
|
||||
try {
|
||||
Network.fromNetworkHandle(100);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {}
|
||||
try {
|
||||
Network.fromNetworkHandle(-1);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {}
|
||||
try {
|
||||
Network.fromNetworkHandle(0);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
39
tests/cts/net/src/android/net/cts/NetworkRequestTest.java
Normal file
39
tests/cts/net/src/android/net/cts/NetworkRequestTest.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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;
|
||||
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
|
||||
|
||||
import android.net.NetworkRequest;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
public class NetworkRequestTest extends AndroidTestCase {
|
||||
public void testCapabilities() {
|
||||
assertTrue(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build()
|
||||
.hasCapability(NET_CAPABILITY_MMS));
|
||||
assertFalse(new NetworkRequest.Builder().removeCapability(NET_CAPABILITY_MMS).build()
|
||||
.hasCapability(NET_CAPABILITY_MMS));
|
||||
}
|
||||
|
||||
public void testTransports() {
|
||||
assertTrue(new NetworkRequest.Builder().addTransportType(TRANSPORT_BLUETOOTH).build()
|
||||
.hasTransport(TRANSPORT_BLUETOOTH));
|
||||
assertFalse(new NetworkRequest.Builder().removeTransportType(TRANSPORT_BLUETOOTH).build()
|
||||
.hasTransport(TRANSPORT_BLUETOOTH));
|
||||
}
|
||||
}
|
||||
140
tests/cts/net/src/android/net/cts/NetworkWatchlistTest.java
Normal file
140
tests/cts/net/src/android/net/cts/NetworkWatchlistTest.java
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.FileUtils;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
|
||||
import com.android.compatibility.common.util.ApiLevelUtil;
|
||||
import com.android.compatibility.common.util.SystemUtil;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Formatter;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class NetworkWatchlistTest {
|
||||
|
||||
private static final String TEST_WATCHLIST_XML = "assets/network_watchlist_config_for_test.xml";
|
||||
private static final String TEST_EMPTY_WATCHLIST_XML =
|
||||
"assets/network_watchlist_config_empty_for_test.xml";
|
||||
private static final String SDCARD_CONFIG_PATH =
|
||||
"/sdcard/network_watchlist_config_for_test.xml";
|
||||
private static final String TMP_CONFIG_PATH =
|
||||
"/data/local/tmp/network_watchlist_config_for_test.xml";
|
||||
// Generated from sha256sum network_watchlist_config_for_test.xml
|
||||
private static final String TEST_WATCHLIST_CONFIG_HASH =
|
||||
"B5FC4636994180D54E1E912F78178AB1D8BD2BE71D90CA9F5BBC3284E4D04ED4";
|
||||
|
||||
private ConnectivityManager mConnectivityManager;
|
||||
private boolean mHasFeature;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mHasFeature = isAtLeastP();
|
||||
mConnectivityManager =
|
||||
(ConnectivityManager) InstrumentationRegistry.getContext().getSystemService(
|
||||
Context.CONNECTIVITY_SERVICE);
|
||||
assumeTrue(mHasFeature);
|
||||
// Set empty watchlist test config before testing
|
||||
setWatchlistConfig(TEST_EMPTY_WATCHLIST_XML);
|
||||
// Verify test watchlist config is not set before testing
|
||||
byte[] result = mConnectivityManager.getNetworkWatchlistConfigHash();
|
||||
assertNotEquals(TEST_WATCHLIST_CONFIG_HASH, byteArrayToHexString(result));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (mHasFeature) {
|
||||
// Set empty watchlist test config after testing
|
||||
setWatchlistConfig(TEST_EMPTY_WATCHLIST_XML);
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanup() throws Exception {
|
||||
runCommand("rm " + SDCARD_CONFIG_PATH);
|
||||
runCommand("rm " + TMP_CONFIG_PATH);
|
||||
}
|
||||
|
||||
private boolean isAtLeastP() throws Exception {
|
||||
// TODO: replace with ApiLevelUtil.isAtLeast(Build.VERSION_CODES.P) when the P API level
|
||||
// constant is defined.
|
||||
return ApiLevelUtil.getCodename().compareToIgnoreCase("P") >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if ConnectivityManager.getNetworkWatchlistConfigHash() correctly
|
||||
* returns the hash of config we set.
|
||||
*/
|
||||
@Test
|
||||
public void testGetWatchlistConfigHash() throws Exception {
|
||||
// Set watchlist config file for test
|
||||
setWatchlistConfig(TEST_WATCHLIST_XML);
|
||||
// Test if watchlist config hash value is correct
|
||||
byte[] result = mConnectivityManager.getNetworkWatchlistConfigHash();
|
||||
Assert.assertEquals(TEST_WATCHLIST_CONFIG_HASH, byteArrayToHexString(result));
|
||||
}
|
||||
|
||||
private static String byteArrayToHexString(byte[] bytes) {
|
||||
Formatter formatter = new Formatter();
|
||||
for (byte b : bytes) {
|
||||
formatter.format("%02X", b);
|
||||
}
|
||||
return formatter.toString();
|
||||
}
|
||||
|
||||
private void saveResourceToFile(String res, String filePath) throws IOException {
|
||||
InputStream in = getClass().getClassLoader().getResourceAsStream(res);
|
||||
FileUtils.copyToFileOrThrow(in, new File(filePath));
|
||||
}
|
||||
|
||||
private static String runCommand(String command) throws IOException {
|
||||
return SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
|
||||
}
|
||||
|
||||
private void setWatchlistConfig(String watchlistConfigFile) throws Exception {
|
||||
cleanup();
|
||||
// Save test watchlist config to sdcard as app can't access /data/local/tmp
|
||||
saveResourceToFile(watchlistConfigFile, SDCARD_CONFIG_PATH);
|
||||
// Copy test watchlist config from sdcard to /data/local/tmp as system service
|
||||
// can't access /sdcard
|
||||
runCommand("cp " + SDCARD_CONFIG_PATH + " " + TMP_CONFIG_PATH);
|
||||
// Set test watchlist config to system
|
||||
final String cmdResult = runCommand(
|
||||
"cmd network_watchlist set-test-config " + TMP_CONFIG_PATH).trim();
|
||||
assertThat(cmdResult).contains("Success");
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
@@ -81,26 +81,6 @@ public class TrafficStatsTest extends AndroidTestCase {
|
||||
return packetCount * (20 + 32 + bytes);
|
||||
}
|
||||
|
||||
private void accessOwnTrafficStats() throws IOException {
|
||||
final int ownAppUid = getContext().getApplicationInfo().uid;
|
||||
Log.d(LOG_TAG, "accesOwnTrafficStatsWithTags(): about to read qtaguid stats for own uid " + ownAppUid);
|
||||
|
||||
boolean foundOwnDetailedStats = false;
|
||||
try {
|
||||
BufferedReader qtaguidReader = new BufferedReader(new FileReader("/proc/net/xt_qtaguid/stats"));
|
||||
String line;
|
||||
while ((line = qtaguidReader.readLine()) != null) {
|
||||
String tokens[] = line.split(" ");
|
||||
if (tokens.length > 3 && tokens[3].equals(String.valueOf(ownAppUid))) {
|
||||
Log.d(LOG_TAG, "accessOwnTrafficStatsWithTags(): got own stats: " + line);
|
||||
}
|
||||
}
|
||||
qtaguidReader.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
fail("Was not able to access qtaguid/stats: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
public void testTrafficStatsForLocalhost() throws IOException {
|
||||
final long mobileTxPacketsBefore = TrafficStats.getMobileTxPackets();
|
||||
final long mobileRxPacketsBefore = TrafficStats.getMobileRxPackets();
|
||||
@@ -132,7 +112,6 @@ public class TrafficStatsTest extends AndroidTestCase {
|
||||
byte[] buf = new byte[byteCount];
|
||||
TrafficStats.setThreadStatsTag(0x42);
|
||||
TrafficStats.tagSocket(socket);
|
||||
accessOwnTrafficStats();
|
||||
for (int i = 0; i < packetCount; i++) {
|
||||
out.write(buf);
|
||||
out.flush();
|
||||
@@ -145,7 +124,6 @@ public class TrafficStatsTest extends AndroidTestCase {
|
||||
}
|
||||
out.close();
|
||||
socket.close();
|
||||
accessOwnTrafficStats();
|
||||
} catch (IOException e) {
|
||||
Log.i(LOG_TAG, "Badness during writes to socket: " + e);
|
||||
}
|
||||
|
||||
@@ -114,6 +114,12 @@ public class UriTest extends AndroidTestCase {
|
||||
assertEquals("a:a@example.com:a@example2.com", uri.getAuthority());
|
||||
assertEquals("example2.com", uri.getHost());
|
||||
assertEquals(-1, uri.getPort());
|
||||
assertEquals("/path", uri.getPath());
|
||||
|
||||
uri = Uri.parse("http://a.foo.com\\.example.com/path");
|
||||
assertEquals("a.foo.com", uri.getHost());
|
||||
assertEquals(-1, uri.getPort());
|
||||
assertEquals("\\.example.com/path", uri.getPath());
|
||||
}
|
||||
|
||||
public void testCompareTo() {
|
||||
|
||||
2
tests/cts/net/src/android/net/wifi/aware/OWNERS
Normal file
2
tests/cts/net/src/android/net/wifi/aware/OWNERS
Normal file
@@ -0,0 +1,2 @@
|
||||
etancohen@google.com
|
||||
satk@google.com
|
||||
@@ -20,7 +20,9 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.location.LocationManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.MacAddress;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.wifi.WifiManager;
|
||||
@@ -37,14 +39,11 @@ import android.net.wifi.aware.WifiAwareManager;
|
||||
import android.net.wifi.aware.WifiAwareSession;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.provider.Settings;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@@ -76,13 +75,6 @@ public class SingleDeviceTest extends AndroidTestCase {
|
||||
// used to store any WifiAwareSession allocated during tests - will clean-up after tests
|
||||
private List<WifiAwareSession> mSessions = new ArrayList<>();
|
||||
|
||||
// Return true if location is enabled.
|
||||
private boolean isLocationEnabled() {
|
||||
return Settings.Secure.getInt(getContext().getContentResolver(),
|
||||
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) !=
|
||||
Settings.Secure.LOCATION_MODE_OFF;
|
||||
}
|
||||
|
||||
private class WifiAwareBroadcastReceiver extends BroadcastReceiver {
|
||||
private CountDownLatch mBlocker = new CountDownLatch(1);
|
||||
|
||||
@@ -358,6 +350,10 @@ public class SingleDeviceTest extends AndroidTestCase {
|
||||
return;
|
||||
}
|
||||
|
||||
assertTrue("Wi-Fi Aware requires Location to be Enabled",
|
||||
((LocationManager) getContext().getSystemService(
|
||||
Context.LOCATION_SERVICE)).isLocationEnabled());
|
||||
|
||||
mWifiAwareManager = (WifiAwareManager) getContext().getSystemService(
|
||||
Context.WIFI_AWARE_SERVICE);
|
||||
assertNotNull("Wi-Fi Aware Manager", mWifiAwareManager);
|
||||
@@ -431,18 +427,6 @@ public class SingleDeviceTest extends AndroidTestCase {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isLocationEnabled()) {
|
||||
/* Can't execute this test with location on since it means that Aware will not get
|
||||
* disabled even if we disable Wi-Fi (which when location is enabled does not correspond
|
||||
* to disabling the Wi-Fi chip).
|
||||
*
|
||||
* Considering other tests may require locationing to be enable we can't also fail the
|
||||
* test in such a case. Hence it is skipped.
|
||||
*/
|
||||
Log.d(TAG, "Skipping test since location scans are enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED);
|
||||
|
||||
@@ -717,82 +701,14 @@ public class SingleDeviceTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Request an Aware data-path (open) on a Publish discovery session (which can be done with a
|
||||
* null peer - to accept all requests). Validate that times-out.
|
||||
*/
|
||||
public void testDataPathOpenInContextOfDiscoveryFail() {
|
||||
if (!TestUtils.shouldTestWifiAware(getContext())) {
|
||||
return;
|
||||
}
|
||||
|
||||
WifiAwareSession session = attachAndGetSession();
|
||||
|
||||
PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(
|
||||
"ValidName").build();
|
||||
DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest();
|
||||
NetworkCallbackTest networkCb = new NetworkCallbackTest();
|
||||
|
||||
// 1. publish
|
||||
session.publish(publishConfig, discoveryCb, mHandler);
|
||||
assertTrue("Publish started",
|
||||
discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_PUBLISH_STARTED));
|
||||
PublishDiscoverySession discoverySession = discoveryCb.getPublishDiscoverySession();
|
||||
assertNotNull("Publish session", discoverySession);
|
||||
|
||||
// 2. request an AWARE network
|
||||
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
|
||||
NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
|
||||
discoverySession.createNetworkSpecifierOpen(null)).build();
|
||||
mConnectivityManager.requestNetwork(nr, networkCb, 2000);
|
||||
assertTrue("OnUnavailable received", networkCb.waitForOnUnavailable());
|
||||
|
||||
discoverySession.close();
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request an Aware data-path (encrypted) on a Publish discovery session (which can be done
|
||||
* with a null peer - to accept all requests). Validate that times-out.
|
||||
*/
|
||||
public void testDataPathPassphraseInContextOfDiscoveryFail() {
|
||||
if (!TestUtils.shouldTestWifiAware(getContext())) {
|
||||
return;
|
||||
}
|
||||
|
||||
WifiAwareSession session = attachAndGetSession();
|
||||
|
||||
PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(
|
||||
"ValidName").build();
|
||||
DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest();
|
||||
NetworkCallbackTest networkCb = new NetworkCallbackTest();
|
||||
|
||||
// 1. publish
|
||||
session.publish(publishConfig, discoveryCb, mHandler);
|
||||
assertTrue("Publish started",
|
||||
discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_PUBLISH_STARTED));
|
||||
PublishDiscoverySession discoverySession = discoveryCb.getPublishDiscoverySession();
|
||||
assertNotNull("Publish session", discoverySession);
|
||||
|
||||
// 2. request an AWARE network
|
||||
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
|
||||
NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
|
||||
discoverySession.createNetworkSpecifierPassphrase(null,
|
||||
"Some very long but not very good passphrase")).build();
|
||||
mConnectivityManager.requestNetwork(nr, networkCb, 2000);
|
||||
assertTrue("OnUnavailable received", networkCb.waitForOnUnavailable());
|
||||
|
||||
discoverySession.close();
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request an Aware data-path (open) as a Responder with no peer MAC address (i.e. accept any
|
||||
* peer request). Validate that times-out.
|
||||
* Request an Aware data-path (open) as a Responder with an arbitrary peer MAC address. Validate
|
||||
* that times-out.
|
||||
*/
|
||||
public void testDataPathOpenOutOfBandFail() {
|
||||
if (!TestUtils.shouldTestWifiAware(getContext())) {
|
||||
return;
|
||||
}
|
||||
MacAddress mac = MacAddress.fromString("00:01:02:03:04:05");
|
||||
|
||||
WifiAwareSession session = attachAndGetSession();
|
||||
|
||||
@@ -805,7 +721,8 @@ public class SingleDeviceTest extends AndroidTestCase {
|
||||
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
|
||||
NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
|
||||
session.createNetworkSpecifierOpen(
|
||||
WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, null)).build();
|
||||
WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER,
|
||||
mac.toByteArray())).build();
|
||||
mConnectivityManager.requestNetwork(nr, networkCb, 2000);
|
||||
assertTrue("OnUnavailable received", networkCb.waitForOnUnavailable());
|
||||
|
||||
@@ -813,13 +730,14 @@ public class SingleDeviceTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Request an Aware data-path (encrypted) as a Responder with no peer MAC address (i.e.
|
||||
* accept any peer request). Validate that times-out.
|
||||
* Request an Aware data-path (encrypted) as a Responder with an arbitrary peer MAC address.
|
||||
* Validate that times-out.
|
||||
*/
|
||||
public void testDataPathPassphraseOutOfBandFail() {
|
||||
if (!TestUtils.shouldTestWifiAware(getContext())) {
|
||||
return;
|
||||
}
|
||||
MacAddress mac = MacAddress.fromString("00:01:02:03:04:05");
|
||||
|
||||
WifiAwareSession session = attachAndGetSession();
|
||||
|
||||
@@ -832,7 +750,7 @@ public class SingleDeviceTest extends AndroidTestCase {
|
||||
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
|
||||
NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
|
||||
session.createNetworkSpecifierPassphrase(
|
||||
WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, null,
|
||||
WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, mac.toByteArray(),
|
||||
"abcdefghihk")).build();
|
||||
mConnectivityManager.requestNetwork(nr, networkCb, 2000);
|
||||
assertTrue("OnUnavailable received", networkCb.waitForOnUnavailable());
|
||||
|
||||
@@ -42,12 +42,14 @@ public class ScanResultTest extends AndroidTestCase {
|
||||
private static final int STATE_WIFI_CHANGED = 2;
|
||||
private static final int STATE_START_SCAN = 3;
|
||||
private static final int STATE_SCAN_RESULTS_AVAILABLE = 4;
|
||||
private static final int STATE_SCAN_FAILURE = 5;
|
||||
|
||||
private static final String TAG = "WifiInfoTest";
|
||||
private static final int TIMEOUT_MSEC = 6000;
|
||||
private static final int WAIT_MSEC = 60;
|
||||
private static final int ENABLE_WAIT_MSEC = 10000;
|
||||
private static final int SCAN_WAIT_MSEC = 10000;
|
||||
private static final int SCAN_MAX_RETRY_COUNT = 6;
|
||||
private IntentFilter mIntentFilter;
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
@@ -60,7 +62,11 @@ public class ScanResultTest extends AndroidTestCase {
|
||||
}
|
||||
} else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
|
||||
synchronized (mMySync) {
|
||||
mMySync.expectedState = STATE_SCAN_RESULTS_AVAILABLE;
|
||||
if (intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)) {
|
||||
mMySync.expectedState = STATE_SCAN_RESULTS_AVAILABLE;
|
||||
} else {
|
||||
mMySync.expectedState = STATE_SCAN_FAILURE;
|
||||
}
|
||||
mMySync.notify();
|
||||
}
|
||||
}
|
||||
@@ -120,11 +126,12 @@ public class ScanResultTest extends AndroidTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForBroadcast(long timeout, int expectedState) throws Exception {
|
||||
private boolean waitForBroadcast(long timeout, int expectedState) throws Exception {
|
||||
long waitTime = System.currentTimeMillis() + timeout;
|
||||
while (System.currentTimeMillis() < waitTime
|
||||
&& mMySync.expectedState != expectedState)
|
||||
mMySync.wait(WAIT_MSEC);
|
||||
return mMySync.expectedState == expectedState;
|
||||
}
|
||||
|
||||
public void testScanResultProperties() {
|
||||
@@ -140,11 +147,16 @@ public class ScanResultTest extends AndroidTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/* Multiple scans to ensure bssid is updated */
|
||||
private void scanAndWait() throws Exception {
|
||||
synchronized (mMySync) {
|
||||
mMySync.expectedState = STATE_START_SCAN;
|
||||
mWifiManager.startScan();
|
||||
waitForBroadcast(SCAN_WAIT_MSEC, STATE_SCAN_RESULTS_AVAILABLE);
|
||||
for (int retry = 0; retry < SCAN_MAX_RETRY_COUNT; retry++) {
|
||||
mMySync.expectedState = STATE_START_SCAN;
|
||||
mWifiManager.startScan();
|
||||
if (waitForBroadcast(SCAN_WAIT_MSEC, STATE_SCAN_RESULTS_AVAILABLE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,9 +169,6 @@ public class ScanResultTest extends AndroidTestCase {
|
||||
long timestamp = 0;
|
||||
String BSSID = null;
|
||||
|
||||
/* Multiple scans to ensure bssid is updated */
|
||||
scanAndWait();
|
||||
scanAndWait();
|
||||
scanAndWait();
|
||||
|
||||
List<ScanResult> scanResults = mWifiManager.getScanResults();
|
||||
@@ -170,8 +179,6 @@ public class ScanResultTest extends AndroidTestCase {
|
||||
break;
|
||||
}
|
||||
|
||||
scanAndWait();
|
||||
scanAndWait();
|
||||
scanAndWait();
|
||||
|
||||
scanResults = mWifiManager.getScanResults();
|
||||
|
||||
@@ -70,7 +70,7 @@ public class WifiManagerTest extends AndroidTestCase {
|
||||
private static final int STATE_WIFI_ENABLED = 2;
|
||||
private static final int STATE_WIFI_DISABLED = 3;
|
||||
private static final int STATE_SCANNING = 4;
|
||||
private static final int STATE_SCAN_RESULTS_AVAILABLE = 5;
|
||||
private static final int STATE_SCAN_DONE = 5;
|
||||
|
||||
private static final String TAG = "WifiManagerTest";
|
||||
private static final String SSID1 = "\"WifiManagerTest\"";
|
||||
@@ -96,13 +96,15 @@ public class WifiManagerTest extends AndroidTestCase {
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
|
||||
|
||||
synchronized (mMySync) {
|
||||
if (mWifiManager.getScanResults() != null) {
|
||||
if (intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)) {
|
||||
mScanResults = mWifiManager.getScanResults();
|
||||
mMySync.expectedState = STATE_SCAN_RESULTS_AVAILABLE;
|
||||
mScanResults = mWifiManager.getScanResults();
|
||||
mMySync.notifyAll();
|
||||
} else {
|
||||
mScanResults = null;
|
||||
}
|
||||
mMySync.expectedState = STATE_SCAN_DONE;
|
||||
mMySync.notifyAll();
|
||||
}
|
||||
} else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
|
||||
int newState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
|
||||
@@ -201,6 +203,25 @@ public class WifiManagerTest extends AndroidTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
// Get the current scan status from sticky broadcast.
|
||||
private boolean isScanCurrentlyAvailable() {
|
||||
boolean isAvailable = false;
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(WifiManager.WIFI_SCAN_AVAILABLE);
|
||||
Intent intent = mContext.registerReceiver(null, intentFilter);
|
||||
assertNotNull(intent);
|
||||
if (intent.getAction().equals(WifiManager.WIFI_SCAN_AVAILABLE)) {
|
||||
int state = intent.getIntExtra(
|
||||
WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_UNKNOWN);
|
||||
if (state == WifiManager.WIFI_STATE_ENABLED) {
|
||||
isAvailable = true;
|
||||
} else if (state == WifiManager.WIFI_STATE_DISABLED) {
|
||||
isAvailable = false;
|
||||
}
|
||||
}
|
||||
return isAvailable;
|
||||
}
|
||||
|
||||
private void startScan() throws Exception {
|
||||
synchronized (mMySync) {
|
||||
mMySync.expectedState = STATE_SCANNING;
|
||||
@@ -245,8 +266,7 @@ public class WifiManagerTest extends AndroidTestCase {
|
||||
* 1.reconnect
|
||||
* 2.reassociate
|
||||
* 3.disconnect
|
||||
* 4.pingSupplicant
|
||||
* 5.satrtScan
|
||||
* 4.createWifiLock
|
||||
*/
|
||||
public void testWifiManagerActions() throws Exception {
|
||||
if (!WifiFeature.isWifiSupported(getContext())) {
|
||||
@@ -256,10 +276,31 @@ public class WifiManagerTest extends AndroidTestCase {
|
||||
assertTrue(mWifiManager.reconnect());
|
||||
assertTrue(mWifiManager.reassociate());
|
||||
assertTrue(mWifiManager.disconnect());
|
||||
final String TAG = "Test";
|
||||
assertNotNull(mWifiManager.createWifiLock(TAG));
|
||||
assertNotNull(mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test wifi scanning when location scan is turned off.
|
||||
*/
|
||||
public void testWifiManagerScanWhenWifiOffLocationTurnedOn() throws Exception {
|
||||
if (!WifiFeature.isWifiSupported(getContext())) {
|
||||
// skip the test if WiFi is not supported
|
||||
return;
|
||||
}
|
||||
if (!hasLocationFeature()) {
|
||||
Log.d(TAG, "Skipping test as location is not supported");
|
||||
return;
|
||||
}
|
||||
if (!isLocationEnabled()) {
|
||||
fail("Please enable location for this test - since Marshmallow WiFi scan results are"
|
||||
+ " empty when location is disabled!");
|
||||
}
|
||||
setWifiEnabled(false);
|
||||
startScan();
|
||||
Thread.sleep(DURATION);
|
||||
if (mWifiManager.isScanAlwaysAvailable()) {
|
||||
startScan();
|
||||
if (mWifiManager.isScanAlwaysAvailable() && isScanCurrentlyAvailable()) {
|
||||
// Make sure at least one AP is found.
|
||||
assertNotNull("mScanResult should not be null!", mScanResults);
|
||||
assertFalse("empty scan results!", mScanResults.isEmpty());
|
||||
@@ -833,10 +874,9 @@ public class WifiManagerTest extends AndroidTestCase {
|
||||
|
||||
TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
|
||||
|
||||
// at this point, wifi should be off
|
||||
assertFalse(mWifiManager.isWifiEnabled());
|
||||
|
||||
stopLocalOnlyHotspot(callback, wifiEnabled);
|
||||
|
||||
// wifi should either stay on, or come back on
|
||||
assertEquals(wifiEnabled, mWifiManager.isWifiEnabled());
|
||||
}
|
||||
|
||||
@@ -848,7 +888,7 @@ public class WifiManagerTest extends AndroidTestCase {
|
||||
* tethering is started.
|
||||
* Note: Location mode must be enabled for this test.
|
||||
*/
|
||||
public void testSetWifiEnabledByAppDoesNotStopHotspot() {
|
||||
public void testSetWifiEnabledByAppDoesNotStopHotspot() throws Exception {
|
||||
if (!WifiFeature.isWifiSupported(getContext())) {
|
||||
// skip the test if WiFi is not supported
|
||||
return;
|
||||
@@ -860,15 +900,18 @@ public class WifiManagerTest extends AndroidTestCase {
|
||||
|
||||
boolean wifiEnabled = mWifiManager.isWifiEnabled();
|
||||
|
||||
if (wifiEnabled) {
|
||||
// disable wifi so we have something to turn on (some devices may be able to run
|
||||
// simultaneous modes)
|
||||
setWifiEnabled(false);
|
||||
}
|
||||
|
||||
TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
|
||||
// at this point, wifi should be off
|
||||
assertFalse(mWifiManager.isWifiEnabled());
|
||||
|
||||
// now we should fail to turn on wifi
|
||||
assertFalse(mWifiManager.setWifiEnabled(true));
|
||||
|
||||
stopLocalOnlyHotspot(callback, wifiEnabled);
|
||||
assertEquals(wifiEnabled, mWifiManager.isWifiEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -892,9 +935,6 @@ public class WifiManagerTest extends AndroidTestCase {
|
||||
|
||||
TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
|
||||
|
||||
// at this point, wifi should be off
|
||||
assertFalse(mWifiManager.isWifiEnabled());
|
||||
|
||||
// now make a second request - this should fail.
|
||||
TestLocalOnlyHotspotCallback callback2 = new TestLocalOnlyHotspotCallback(mLOHSLock);
|
||||
try {
|
||||
@@ -903,9 +943,12 @@ public class WifiManagerTest extends AndroidTestCase {
|
||||
Log.d(TAG, "Caught the IllegalStateException we expected: called startLOHS twice");
|
||||
caughtException = true;
|
||||
}
|
||||
if (!caughtException) {
|
||||
// second start did not fail, should clean up the hotspot.
|
||||
stopLocalOnlyHotspot(callback2, wifiEnabled);
|
||||
}
|
||||
assertTrue(caughtException);
|
||||
|
||||
stopLocalOnlyHotspot(callback, wifiEnabled);
|
||||
assertEquals(wifiEnabled, mWifiManager.isWifiEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
2
tests/cts/net/src/android/net/wifi/rtt/OWNERS
Normal file
2
tests/cts/net/src/android/net/wifi/rtt/OWNERS
Normal file
@@ -0,0 +1,2 @@
|
||||
etancohen@google.com
|
||||
satk@google.com
|
||||
235
tests/cts/net/src/android/net/wifi/rtt/cts/TestBase.java
Normal file
235
tests/cts/net/src/android/net/wifi/rtt/cts/TestBase.java
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.wifi.rtt.cts;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.location.LocationManager;
|
||||
import android.net.wifi.ScanResult;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.net.wifi.rtt.RangingResult;
|
||||
import android.net.wifi.rtt.RangingResultCallback;
|
||||
import android.net.wifi.rtt.WifiRttManager;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerExecutor;
|
||||
import android.os.HandlerThread;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Base class for Wi-Fi RTT CTS test cases. Provides a uniform configuration and event management
|
||||
* facility.
|
||||
*/
|
||||
public class TestBase extends AndroidTestCase {
|
||||
protected static final String TAG = "WifiRttCtsTests";
|
||||
|
||||
// wait for Wi-Fi RTT to become available
|
||||
private static final int WAIT_FOR_RTT_CHANGE_SECS = 10;
|
||||
|
||||
// wait for Wi-Fi scan results to become available
|
||||
private static final int WAIT_FOR_SCAN_RESULTS_SECS = 20;
|
||||
|
||||
protected WifiRttManager mWifiRttManager;
|
||||
protected WifiManager mWifiManager;
|
||||
private LocationManager mLocationManager;
|
||||
private WifiManager.WifiLock mWifiLock;
|
||||
|
||||
private final HandlerThread mHandlerThread = new HandlerThread("SingleDeviceTest");
|
||||
protected final Executor mExecutor;
|
||||
{
|
||||
mHandlerThread.start();
|
||||
mExecutor = new HandlerExecutor(new Handler(mHandlerThread.getLooper()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a flag indicating whether or not Wi-Fi RTT should be tested. Wi-Fi RTT
|
||||
* should be tested if the feature is supported on the current device.
|
||||
*/
|
||||
static boolean shouldTestWifiRtt(Context context) {
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
return pm.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
if (!shouldTestWifiRtt(getContext())) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLocationManager = (LocationManager) getContext().getSystemService(
|
||||
Context.LOCATION_SERVICE);
|
||||
assertTrue("RTT testing requires Location to be enabled",
|
||||
mLocationManager.isLocationEnabled());
|
||||
|
||||
mWifiRttManager = (WifiRttManager) getContext().getSystemService(
|
||||
Context.WIFI_RTT_RANGING_SERVICE);
|
||||
assertNotNull("Wi-Fi RTT Manager", mWifiRttManager);
|
||||
|
||||
mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
|
||||
assertNotNull("Wi-Fi Manager", mWifiManager);
|
||||
mWifiLock = mWifiManager.createWifiLock(TAG);
|
||||
mWifiLock.acquire();
|
||||
if (!mWifiManager.isWifiEnabled()) {
|
||||
mWifiManager.setWifiEnabled(true);
|
||||
}
|
||||
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED);
|
||||
WifiRttBroadcastReceiver receiver = new WifiRttBroadcastReceiver();
|
||||
mContext.registerReceiver(receiver, intentFilter);
|
||||
if (!mWifiRttManager.isAvailable()) {
|
||||
assertTrue("Timeout waiting for Wi-Fi RTT to change status",
|
||||
receiver.waitForStateChange());
|
||||
assertTrue("Wi-Fi RTT is not available (should be)", mWifiRttManager.isAvailable());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (!shouldTestWifiRtt(getContext())) {
|
||||
super.tearDown();
|
||||
return;
|
||||
}
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
class WifiRttBroadcastReceiver extends BroadcastReceiver {
|
||||
private CountDownLatch mBlocker = new CountDownLatch(1);
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED.equals(intent.getAction())) {
|
||||
mBlocker.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
boolean waitForStateChange() throws InterruptedException {
|
||||
return mBlocker.await(WAIT_FOR_RTT_CHANGE_SECS, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
class WifiScansBroadcastReceiver extends BroadcastReceiver {
|
||||
private CountDownLatch mBlocker = new CountDownLatch(1);
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) {
|
||||
mBlocker.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
boolean waitForStateChange() throws InterruptedException {
|
||||
return mBlocker.await(WAIT_FOR_SCAN_RESULTS_SECS, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
class ResultCallback extends RangingResultCallback {
|
||||
private CountDownLatch mBlocker = new CountDownLatch(1);
|
||||
private int mCode; // 0: success, otherwise RangingResultCallback STATUS_CODE_*.
|
||||
private List<RangingResult> mResults;
|
||||
|
||||
@Override
|
||||
public void onRangingFailure(int code) {
|
||||
mCode = code;
|
||||
mResults = null; // not necessary since intialized to null - but for completeness
|
||||
mBlocker.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRangingResults(List<RangingResult> results) {
|
||||
mCode = 0; // not necessary since initialized to 0 - but for completeness
|
||||
mResults = results;
|
||||
mBlocker.countDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the listener callback to be called - or an error (timeout, interruption).
|
||||
* Returns true on callback called, false on error (timeout, interruption).
|
||||
*/
|
||||
boolean waitForCallback() throws InterruptedException {
|
||||
return mBlocker.await(WAIT_FOR_RTT_CHANGE_SECS, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code of the callback operation. Will be 0 for success (onRangingResults
|
||||
* called), else (if onRangingFailure called) will be one of the STATUS_CODE_* values.
|
||||
*/
|
||||
int getCode() {
|
||||
return mCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of ranging results. In cases of error (getCode() != 0) will return null.
|
||||
*/
|
||||
List<RangingResult> getResults() {
|
||||
return mResults;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a scan and return a list of observed ScanResults (APs).
|
||||
*/
|
||||
protected List<ScanResult> scanAps() throws InterruptedException {
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
|
||||
WifiScansBroadcastReceiver receiver = new WifiScansBroadcastReceiver();
|
||||
mContext.registerReceiver(receiver, intentFilter);
|
||||
|
||||
mWifiManager.startScan();
|
||||
receiver.waitForStateChange();
|
||||
mContext.unregisterReceiver(receiver);
|
||||
return mWifiManager.getScanResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a scan and return a test AP which supports IEEE 802.11mc and which has the highest
|
||||
* RSSI. Will perform N (parameterized) scans and get the best AP across both scans.
|
||||
*
|
||||
* Returns null if test AP is not found in the specified number of scans.
|
||||
*
|
||||
* @param numScanRetries Maximum number of scans retries (in addition to first scan).
|
||||
*/
|
||||
protected ScanResult scanForTestAp(int numScanRetries)
|
||||
throws InterruptedException {
|
||||
int scanCount = 0;
|
||||
ScanResult bestTestAp = null;
|
||||
while (scanCount <= numScanRetries) {
|
||||
for (ScanResult scanResult : scanAps()) {
|
||||
if (!scanResult.is80211mcResponder()) {
|
||||
continue;
|
||||
}
|
||||
if (bestTestAp == null || scanResult.level > bestTestAp.level) {
|
||||
bestTestAp = scanResult;
|
||||
}
|
||||
}
|
||||
|
||||
scanCount++;
|
||||
}
|
||||
|
||||
return bestTestAp;
|
||||
}
|
||||
}
|
||||
210
tests/cts/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
Normal file
210
tests/cts/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.wifi.rtt.cts;
|
||||
|
||||
import android.content.IntentFilter;
|
||||
import android.net.wifi.ScanResult;
|
||||
import android.net.wifi.rtt.RangingRequest;
|
||||
import android.net.wifi.rtt.RangingResult;
|
||||
import android.net.wifi.rtt.WifiRttManager;
|
||||
|
||||
import com.android.compatibility.common.util.DeviceReportLog;
|
||||
import com.android.compatibility.common.util.ResultType;
|
||||
import com.android.compatibility.common.util.ResultUnit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wi-Fi RTT CTS test: range to all available Access Points which support IEEE 802.11mc.
|
||||
*/
|
||||
public class WifiRttTest extends TestBase {
|
||||
// Number of scans to do while searching for APs supporting IEEE 802.11mc
|
||||
private static final int NUM_SCANS_SEARCHING_FOR_IEEE80211MC_AP = 2;
|
||||
|
||||
// Number of RTT measurements per AP
|
||||
private static final int NUM_OF_RTT_ITERATIONS = 10;
|
||||
|
||||
// Maximum failure rate of RTT measurements (percentage)
|
||||
private static final int MAX_FAILURE_RATE_PERCENT = 10;
|
||||
|
||||
// Maximum variation from the average measurement (measures consistency)
|
||||
private static final int MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM = 1000;
|
||||
|
||||
// Minimum valid RSSI value
|
||||
private static final int MIN_VALID_RSSI = -100;
|
||||
|
||||
/**
|
||||
* Test Wi-Fi RTT ranging operation:
|
||||
* - Scan for visible APs for the test AP (which is validated to support IEEE 802.11mc)
|
||||
* - Perform N (constant) RTT operations
|
||||
* - Validate:
|
||||
* - Failure ratio < threshold (constant)
|
||||
* - Result margin < threshold (constant)
|
||||
*/
|
||||
public void testRangingToTestAp() throws InterruptedException {
|
||||
if (!shouldTestWifiRtt(getContext())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scan for IEEE 802.11mc supporting APs
|
||||
ScanResult testAp = scanForTestAp(NUM_SCANS_SEARCHING_FOR_IEEE80211MC_AP);
|
||||
assertTrue("Cannot find test AP", testAp != null);
|
||||
|
||||
// Perform RTT operations
|
||||
RangingRequest request = new RangingRequest.Builder().addAccessPoint(testAp).build();
|
||||
List<RangingResult> allResults = new ArrayList<>();
|
||||
int numFailures = 0;
|
||||
int distanceSum = 0;
|
||||
int distanceMin = 0;
|
||||
int distanceMax = 0;
|
||||
int[] statuses = new int[NUM_OF_RTT_ITERATIONS];
|
||||
int[] distanceMms = new int[NUM_OF_RTT_ITERATIONS];
|
||||
int[] distanceStdDevMms = new int[NUM_OF_RTT_ITERATIONS];
|
||||
int[] rssis = new int[NUM_OF_RTT_ITERATIONS];
|
||||
int[] numAttempted = new int[NUM_OF_RTT_ITERATIONS];
|
||||
int[] numSuccessful = new int[NUM_OF_RTT_ITERATIONS];
|
||||
long[] timestampsMs = new long[NUM_OF_RTT_ITERATIONS];
|
||||
byte[] lastLci = null;
|
||||
byte[] lastLcr = null;
|
||||
for (int i = 0; i < NUM_OF_RTT_ITERATIONS; ++i) {
|
||||
ResultCallback callback = new ResultCallback();
|
||||
mWifiRttManager.startRanging(request, mExecutor, callback);
|
||||
assertTrue("Wi-Fi RTT results: no callback on iteration " + i,
|
||||
callback.waitForCallback());
|
||||
|
||||
List<RangingResult> currentResults = callback.getResults();
|
||||
assertTrue("Wi-Fi RTT results: null results (onRangingFailure) on iteration " + i,
|
||||
currentResults != null);
|
||||
assertTrue("Wi-Fi RTT results: unexpected # of results (expect 1) on iteration " + i,
|
||||
currentResults.size() == 1);
|
||||
RangingResult result = currentResults.get(0);
|
||||
assertTrue("Wi-Fi RTT results: invalid result (wrong BSSID) entry on iteration " + i,
|
||||
result.getMacAddress().toString().equals(testAp.BSSID));
|
||||
assertEquals(
|
||||
"Wi-Fi RTT results: invalid result (non-null PeerHandle) entry on iteration "
|
||||
+ i, null, result.getPeerHandle());
|
||||
|
||||
allResults.add(result);
|
||||
int status = result.getStatus();
|
||||
statuses[i] = status;
|
||||
if (status == RangingResult.STATUS_SUCCESS) {
|
||||
distanceSum += result.getDistanceMm();
|
||||
if (i == 0) {
|
||||
distanceMin = result.getDistanceMm();
|
||||
distanceMax = result.getDistanceMm();
|
||||
} else {
|
||||
distanceMin = Math.min(distanceMin, result.getDistanceMm());
|
||||
distanceMax = Math.max(distanceMax, result.getDistanceMm());
|
||||
}
|
||||
|
||||
assertTrue("Wi-Fi RTT results: invalid RSSI on iteration " + i,
|
||||
result.getRssi() >= MIN_VALID_RSSI);
|
||||
|
||||
distanceMms[i - numFailures] = result.getDistanceMm();
|
||||
distanceStdDevMms[i - numFailures] = result.getDistanceStdDevMm();
|
||||
rssis[i - numFailures] = result.getRssi();
|
||||
numAttempted[i - numFailures] = result.getNumAttemptedMeasurements();
|
||||
numSuccessful[i - numFailures] = result.getNumSuccessfulMeasurements();
|
||||
timestampsMs[i - numFailures] = result.getRangingTimestampMillis();
|
||||
|
||||
byte[] currentLci = result.getLci();
|
||||
byte[] currentLcr = result.getLcr();
|
||||
if (i - numFailures > 0) {
|
||||
assertTrue("Wi-Fi RTT results: invalid result (LCI mismatch) on iteration " + i,
|
||||
Arrays.equals(currentLci, lastLci));
|
||||
assertTrue("Wi-Fi RTT results: invalid result (LCR mismatch) on iteration " + i,
|
||||
Arrays.equals(currentLcr, lastLcr));
|
||||
}
|
||||
lastLci = currentLci;
|
||||
lastLcr = currentLcr;
|
||||
} else {
|
||||
numFailures++;
|
||||
}
|
||||
}
|
||||
|
||||
// Save results to log
|
||||
int numGoodResults = NUM_OF_RTT_ITERATIONS - numFailures;
|
||||
DeviceReportLog reportLog = new DeviceReportLog(TAG, "testRangingToTestAp");
|
||||
reportLog.addValues("status_codes", statuses, ResultType.NEUTRAL, ResultUnit.NONE);
|
||||
reportLog.addValues("distance_mm", Arrays.copyOf(distanceMms, numGoodResults),
|
||||
ResultType.NEUTRAL, ResultUnit.NONE);
|
||||
reportLog.addValues("distance_stddev_mm", Arrays.copyOf(distanceStdDevMms, numGoodResults),
|
||||
ResultType.NEUTRAL, ResultUnit.NONE);
|
||||
reportLog.addValues("rssi_dbm", Arrays.copyOf(rssis, numGoodResults), ResultType.NEUTRAL,
|
||||
ResultUnit.NONE);
|
||||
reportLog.addValues("num_attempted", Arrays.copyOf(numAttempted, numGoodResults),
|
||||
ResultType.NEUTRAL, ResultUnit.NONE);
|
||||
reportLog.addValues("num_successful", Arrays.copyOf(numSuccessful, numGoodResults),
|
||||
ResultType.NEUTRAL, ResultUnit.NONE);
|
||||
reportLog.addValues("timestamps", Arrays.copyOf(timestampsMs, numGoodResults),
|
||||
ResultType.NEUTRAL, ResultUnit.NONE);
|
||||
reportLog.submit();
|
||||
|
||||
// Analyze results
|
||||
assertTrue("Wi-Fi RTT failure rate exceeds threshold",
|
||||
numFailures <= NUM_OF_RTT_ITERATIONS * MAX_FAILURE_RATE_PERCENT / 100);
|
||||
if (numFailures != NUM_OF_RTT_ITERATIONS) {
|
||||
double distanceAvg = distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures);
|
||||
assertTrue("Wi-Fi RTT: Variation (max direction) exceeds threshold",
|
||||
(distanceMax - distanceAvg) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
|
||||
assertTrue("Wi-Fi RTT: Variation (min direction) exceeds threshold",
|
||||
(distanceAvg - distanceMin) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
|
||||
for (int i = 0; i < numGoodResults; ++i) {
|
||||
assertNotSame("Number of attempted measurements is 0", 0, numAttempted[i]);
|
||||
assertNotSame("Number of successful measurements is 0", 0, numSuccessful[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that when a request contains more range operations than allowed (by API) that we
|
||||
* get an exception.
|
||||
*/
|
||||
public void testRequestTooLarge() {
|
||||
if (!shouldTestWifiRtt(getContext())) {
|
||||
return;
|
||||
}
|
||||
|
||||
ScanResult dummy = new ScanResult();
|
||||
dummy.BSSID = "00:01:02:03:04:05";
|
||||
|
||||
RangingRequest.Builder builder = new RangingRequest.Builder();
|
||||
for (int i = 0; i < RangingRequest.getMaxPeers() - 2; ++i) {
|
||||
builder.addAccessPoint(dummy);
|
||||
}
|
||||
|
||||
List<ScanResult> scanResults = new ArrayList<>();
|
||||
scanResults.add(dummy);
|
||||
scanResults.add(dummy);
|
||||
scanResults.add(dummy);
|
||||
|
||||
builder.addAccessPoints(scanResults);
|
||||
|
||||
try {
|
||||
mWifiRttManager.startRanging(builder.build(), mExecutor, new ResultCallback());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
assertTrue(
|
||||
"Did not receive expected IllegalArgumentException when tried to range to too "
|
||||
+ "many peers",
|
||||
false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user