Merge Android Pie into master

Bug: 112104996
Change-Id: Icf38c8d11828f219c862aed4dbc35e5fddf716f5
This commit is contained in:
Xin Li
2018-08-06 16:50:02 -07:00
31 changed files with 1164 additions and 247 deletions

View File

@@ -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" />

View File

@@ -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

View File

@@ -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" />

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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"/>

View File

@@ -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());

View File

@@ -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. *
*******************/

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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" />

View File

@@ -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
View File

@@ -0,0 +1,2 @@
lorenzo@google.com
satk@google.com

View File

@@ -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>

View 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>

View File

@@ -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" />

View File

@@ -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();

View File

@@ -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);
}
}
}

View File

@@ -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) {}
}
}

View 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));
}
}

View 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();
}
}

View File

@@ -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);
}

View File

@@ -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() {

View File

@@ -0,0 +1,2 @@
etancohen@google.com
satk@google.com

View File

@@ -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());

View File

@@ -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();

View File

@@ -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());
}
}

View File

@@ -0,0 +1,2 @@
etancohen@google.com
satk@google.com

View 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;
}
}

View 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);
}
}