Pull service dumps to help debug test failures.

+ Convert tests to use Junit4
+ Add annotations to specify required conditions for the test to run.

Bug: 137859686
Test: atest hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
Test: atest hostsidetests/net/src/com/android/cts/net/HostsideNetworkCallbackTests.java
Change-Id: I93317c201a0ea06732e29154ab7e140735381f59
This commit is contained in:
Sudheer Shanka
2019-06-25 14:17:35 -07:00
parent 04debd850f
commit 09ae6d2645
24 changed files with 939 additions and 782 deletions

View File

@@ -31,4 +31,9 @@
<option name="jar" value="CtsHostsideNetworkTests.jar" />
<option name="runtime-hint" value="3m56s" />
</test>
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
<option name="directory-keys" value="/sdcard/CtsHostsideNetworkTests" />
<option name="collect-on-run-ended-only" value="true" />
</metrics_collector>
</configuration>

View File

@@ -20,6 +20,8 @@ android_test_helper_app {
//sdk_version: "current",
platform_apis: true,
static_libs: [
"androidx.test.rules",
"androidx.test.ext.junit",
"compatibility-device-util-axt",
"ctstestrunner-axt",
"ub-uiautomator",

View File

@@ -26,8 +26,9 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application>
<application android:requestLegacyExternalStorage="true" >
<uses-library android:name="android.test.runner" />
<activity android:name=".MyActivity" />
<service android:name=".MyVpnService"

View File

@@ -16,20 +16,27 @@
package com.android.cts.net.hostside;
import static com.android.cts.net.hostside.Property.APP_STANDBY_MODE;
import static com.android.cts.net.hostside.Property.BATTERY_SAVER_MODE;
import static org.junit.Assert.assertEquals;
import android.os.SystemClock;
import android.util.Log;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Base class for metered and non-metered tests on idle apps.
*/
@RequiredProperties({APP_STANDBY_MODE})
abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetworkTestCase {
@Override
protected final void setUp() throws Exception {
@Before
public final void setUp() throws Exception {
super.setUp();
if (!isSupported()) return;
// Set initial state.
removePowerSaveModeWhitelist(TEST_APP2_PKG);
removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
@@ -39,41 +46,16 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork
registerBroadcastReceiver();
}
@Override
protected final void tearDown() throws Exception {
@After
public final void tearDown() throws Exception {
super.tearDown();
if (!isSupported()) return;
try {
tearDownMeteredNetwork();
} finally {
turnBatteryOff();
setAppIdle(false);
}
}
@Override
protected boolean isSupported() throws Exception {
boolean supported = isDozeModeEnabled();
if (!supported) {
Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ "() because device does not support Doze Mode");
}
return supported;
}
/**
* Resets the (non) metered network state.
*
* <p>By default is empty - it's up to subclasses to override.
*/
protected void tearDownMeteredNetwork() throws Exception {
turnBatteryOff();
setAppIdle(false);
}
@Test
public void testBackgroundNetworkAccess_enabled() throws Exception {
if (!isSupported()) return;
setAppIdle(true);
assertBackgroundNetworkAccess(false);
@@ -98,9 +80,8 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork
assertBackgroundNetworkAccess(false);
}
@Test
public void testBackgroundNetworkAccess_whitelisted() throws Exception {
if (!isSupported()) return;
setAppIdle(true);
assertBackgroundNetworkAccess(false);
@@ -127,9 +108,8 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork
assertBackgroundNetworkAccess(false);
}
@Test
public void testBackgroundNetworkAccess_tempWhitelisted() throws Exception {
if (!isSupported()) return;
setAppIdle(true);
assertBackgroundNetworkAccess(false);
@@ -140,23 +120,17 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork
assertBackgroundNetworkAccess(false);
}
@Test
public void testBackgroundNetworkAccess_disabled() throws Exception {
if (!isSupported()) return;
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(true);
}
@RequiredProperties({BATTERY_SAVER_MODE})
@Test
public void testAppIdleNetworkAccess_whenCharging() throws Exception {
if (!isBatterySaverSupported()) {
Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ "() because device does not support Battery saver mode");
return;
}
if (!isSupported()) return;
// Check that app is paroled when charging
setAppIdle(true);
assertBackgroundNetworkAccess(false);
@@ -180,9 +154,8 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork
assertBackgroundNetworkAccess(true);
}
@Test
public void testAppIdleNetworkAccess_idleWhitelisted() throws Exception {
if (!isSupported()) return;
setAppIdle(true);
assertAppIdle(true);
assertBackgroundNetworkAccess(false);
@@ -199,9 +172,8 @@ abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetwork
removeAppIdleWhitelist(mUid + 1);
}
@Test
public void testAppIdle_toast() throws Exception {
if (!isSupported()) return;
setAppIdle(true);
assertAppIdle(true);
assertEquals("Shown", showToast());

View File

@@ -16,20 +16,22 @@
package com.android.cts.net.hostside;
import android.text.TextUtils;
import android.util.Log;
import static com.android.cts.net.hostside.Property.BATTERY_SAVER_MODE;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Base class for metered and non-metered Battery Saver Mode tests.
*/
@RequiredProperties({BATTERY_SAVER_MODE})
abstract class AbstractBatterySaverModeTestCase extends AbstractRestrictBackgroundNetworkTestCase {
@Override
protected final void setUp() throws Exception {
@Before
public final void setUp() throws Exception {
super.setUp();
if (!isSupported()) return;
// Set initial state.
removePowerSaveModeWhitelist(TEST_APP2_PKG);
removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
@@ -38,55 +40,15 @@ abstract class AbstractBatterySaverModeTestCase extends AbstractRestrictBackgrou
registerBroadcastReceiver();
}
@Override
protected final void tearDown() throws Exception {
@After
public final void tearDown() throws Exception {
super.tearDown();
if (!isSupported()) return;
try {
tearDownMeteredNetwork();
} finally {
setBatterySaverMode(false);
}
}
@Override
protected boolean isSupported() throws Exception {
String unSupported = "";
if (!isDozeModeEnabled()) {
unSupported += "Doze mode,";
}
if (!isBatterySaverSupported()) {
unSupported += "Battery saver mode,";
}
if (!TextUtils.isEmpty(unSupported)) {
Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ "() because device does not support " + unSupported);
return false;
}
return true;
}
/**
* Sets the initial (non) metered network state.
*
* <p>By default is empty - it's up to subclasses to override.
*/
protected void setUpMeteredNetwork() throws Exception {
}
/**
* Resets the (non) metered network state.
*
* <p>By default is empty - it's up to subclasses to override.
*/
protected void tearDownMeteredNetwork() throws Exception {
setBatterySaverMode(false);
}
@Test
public void testBackgroundNetworkAccess_enabled() throws Exception {
if (!isSupported()) return;
setBatterySaverMode(true);
assertBackgroundNetworkAccess(false);
@@ -118,9 +80,8 @@ abstract class AbstractBatterySaverModeTestCase extends AbstractRestrictBackgrou
assertBackgroundNetworkAccess(false);
}
@Test
public void testBackgroundNetworkAccess_whitelisted() throws Exception {
if (!isSupported()) return;
setBatterySaverMode(true);
assertBackgroundNetworkAccess(false);
@@ -140,9 +101,8 @@ abstract class AbstractBatterySaverModeTestCase extends AbstractRestrictBackgrou
assertBackgroundNetworkAccess(false);
}
@Test
public void testBackgroundNetworkAccess_disabled() throws Exception {
if (!isSupported()) return;
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();

View File

@@ -16,20 +16,25 @@
package com.android.cts.net.hostside;
import static com.android.cts.net.hostside.Property.DOZE_MODE;
import static com.android.cts.net.hostside.Property.NOT_LOW_RAM_DEVICE;
import android.os.SystemClock;
import android.util.Log;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Base class for metered and non-metered Doze Mode tests.
*/
@RequiredProperties({DOZE_MODE})
abstract class AbstractDozeModeTestCase extends AbstractRestrictBackgroundNetworkTestCase {
@Override
protected final void setUp() throws Exception {
@Before
public final void setUp() throws Exception {
super.setUp();
if (!isSupported()) return;
// Set initial state.
removePowerSaveModeWhitelist(TEST_APP2_PKG);
removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
@@ -38,48 +43,15 @@ abstract class AbstractDozeModeTestCase extends AbstractRestrictBackgroundNetwor
registerBroadcastReceiver();
}
@Override
protected final void tearDown() throws Exception {
@After
public final void tearDown() throws Exception {
super.tearDown();
if (!isSupported()) return;
try {
tearDownMeteredNetwork();
} finally {
setDozeMode(false);
}
}
@Override
protected boolean isSupported() throws Exception {
boolean supported = isDozeModeEnabled();
if (!supported) {
Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ "() because device does not support Doze Mode");
}
return supported;
}
/**
* Sets the initial (non) metered network state.
*
* <p>By default is empty - it's up to subclasses to override.
*/
protected void setUpMeteredNetwork() throws Exception {
}
/**
* Resets the (non) metered network state.
*
* <p>By default is empty - it's up to subclasses to override.
*/
protected void tearDownMeteredNetwork() throws Exception {
setDozeMode(false);
}
@Test
public void testBackgroundNetworkAccess_enabled() throws Exception {
if (!isSupported()) return;
setDozeMode(true);
assertBackgroundNetworkAccess(false);
@@ -96,9 +68,8 @@ abstract class AbstractDozeModeTestCase extends AbstractRestrictBackgroundNetwor
assertBackgroundNetworkAccess(false);
}
@Test
public void testBackgroundNetworkAccess_whitelisted() throws Exception {
if (!isSupported()) return;
setDozeMode(true);
assertBackgroundNetworkAccess(false);
@@ -118,19 +89,18 @@ abstract class AbstractDozeModeTestCase extends AbstractRestrictBackgroundNetwor
assertBackgroundNetworkAccess(false);
}
@Test
public void testBackgroundNetworkAccess_disabled() throws Exception {
if (!isSupported()) return;
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(true);
}
@RequiredProperties({NOT_LOW_RAM_DEVICE})
@Test
public void testBackgroundNetworkAccess_enabledButWhitelistedOnNotificationAction()
throws Exception {
if (!isSupported() || isLowRamDevice()) return;
setPendingIntentWhitelistDuration(NETWORK_TIMEOUT_MS);
try {
registerNotificationListenerService();

View File

@@ -17,14 +17,22 @@
package com.android.cts.net.hostside;
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 static com.android.cts.net.hostside.NetworkPolicyTestUtils.executeShellCommand;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getConnectivityManager;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getContext;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getInstrumentation;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getWifiManager;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isDozeModeSupported;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.restrictBackgroundValueToString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.app.ActivityManager;
import android.app.Instrumentation;
@@ -34,9 +42,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo.State;
import android.net.wifi.WifiManager;
@@ -44,24 +50,27 @@ import android.os.BatteryManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.test.InstrumentationTestCase;
import android.text.TextUtils;
import android.util.Log;
import com.android.compatibility.common.util.BatteryUtils;
import org.junit.Rule;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
/**
* Superclass for tests related to background network restrictions.
*/
abstract class AbstractRestrictBackgroundNetworkTestCase extends InstrumentationTestCase {
protected static final String TAG = "RestrictBackgroundNetworkTests";
@RunWith(AndroidJUnit4.class)
public abstract class AbstractRestrictBackgroundNetworkTestCase {
public static final String TAG = "RestrictBackgroundNetworkTests";
protected static final String TEST_PKG = "com.android.cts.net.hostside";
protected static final String TEST_APP2_PKG = "com.android.cts.net.hostside.app2";
@@ -98,8 +107,6 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
static final int NETWORK_TIMEOUT_MS = 15 * SECOND_IN_MS;
private static int PROCESS_STATE_FOREGROUND_SERVICE;
private static final int PROCESS_STATE_TOP = 2;
private static final String KEY_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer";
protected static final int TYPE_COMPONENT_ACTIVTIY = 0;
@@ -126,22 +133,23 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
protected WifiManager mWfm;
protected int mUid;
private int mMyUid;
private String mMeteredWifi;
private MyServiceClient mServiceClient;
private String mDeviceIdleConstantsSetting;
private boolean mSupported;
private boolean mIsLocationOn;
@Override
@Rule
public final RuleChain mRuleChain = RuleChain.outerRule(new DumpOnFailureRule())
.around(new RequiredPropertiesRule())
.around(new MeterednessConfigurationRule());
protected void setUp() throws Exception {
super.setUp();
PROCESS_STATE_FOREGROUND_SERVICE = (Integer) ActivityManager.class
.getDeclaredField("PROCESS_STATE_FOREGROUND_SERVICE").get(null);
mInstrumentation = getInstrumentation();
mContext = mInstrumentation.getContext();
mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
mWfm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mContext = getContext();
mCm = getConnectivityManager();
mWfm = getWifiManager();
mUid = getUid(TEST_APP2_PKG);
mMyUid = getUid(mContext.getPackageName());
mServiceClient = new MyServiceClient(mContext);
@@ -151,10 +159,9 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
if (!mIsLocationOn) {
enableLocation();
}
mSupported = setUpActiveNetworkMeteringState();
setAppIdle(false);
Log.i(TAG, "Apps status on " + getName() + ":\n"
Log.i(TAG, "Apps status:\n"
+ "\ttest app: uid=" + mMyUid + ", state=" + getProcessStateByUid(mMyUid) + "\n"
+ "\tapp2: uid=" + mUid + ", state=" + getProcessStateByUid(mUid));
@@ -165,16 +172,13 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
final String currentConstants =
executeShellCommand("settings get global app_idle_constants");
assertEquals(appIdleConstants, currentConstants);
}
}
@Override
protected void tearDown() throws Exception {
if (!mIsLocationOn) {
disableLocation();
}
mServiceClient.unbind();
super.tearDown();
}
private void enableLocation() throws Exception {
@@ -259,23 +263,8 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
protected void assertRestrictBackgroundStatus(int expectedStatus) throws Exception {
final String status = mServiceClient.getRestrictBackgroundStatus();
assertNotNull("didn't get API status from app2", status);
final String actualStatus = toString(Integer.parseInt(status));
assertEquals("wrong status", toString(expectedStatus), actualStatus);
}
protected void assertMyRestrictBackgroundStatus(int expectedStatus) throws Exception {
final int actualStatus = mCm.getRestrictBackgroundStatus();
assertEquals("Wrong status", toString(expectedStatus), toString(actualStatus));
}
protected boolean isMyRestrictBackgroundStatus(int expectedStatus) throws Exception {
final int actualStatus = mCm.getRestrictBackgroundStatus();
if (expectedStatus != actualStatus) {
Log.d(TAG, "Expected: " + toString(expectedStatus)
+ " but actual: " + toString(actualStatus));
return false;
}
return true;
assertEquals(restrictBackgroundValueToString(expectedStatus),
restrictBackgroundValueToString(Integer.parseInt(status)));
}
protected void assertBackgroundNetworkAccess(boolean expectAllowed) throws Exception {
@@ -297,28 +286,6 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
assertNetworkAccess(true /* expectAvailable */, false /* needScreenOn */);
}
/**
* Whether this device suport this type of test.
*
* <p>Should be overridden when necessary (but always calling
* {@code super.isSupported()} first), and explicitly used before each test
* Example:
*
* <pre><code>
* public void testSomething() {
* if (!isSupported()) return;
* </code></pre>
*
* @return {@code true} by default.
*/
protected boolean isSupported() throws Exception {
return mSupported;
}
protected boolean isBatterySaverSupported() {
return BatteryUtils.isBatterySaverSupported();
}
/**
* Asserts that an app always have access while on foreground or running a foreground service.
*
@@ -387,23 +354,6 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
fail("App2 is not on foreground service state after " + maxTries + " attempts: " + state );
}
/**
* As per CDD requirements, if the device doesn't support data saver mode then
* ConnectivityManager.getRestrictBackgroundStatus() will always return
* RESTRICT_BACKGROUND_STATUS_DISABLED. So, enable the data saver mode and check if
* ConnectivityManager.getRestrictBackgroundStatus() for an app in background returns
* RESTRICT_BACKGROUND_STATUS_DISABLED or not.
*/
protected boolean isDataSaverSupported() throws Exception {
assertMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
try {
setRestrictBackground(true);
return !isMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
} finally {
setRestrictBackground(false);
}
}
/**
* Returns whether an app state should be considered "background" for restriction purposes.
*/
@@ -443,40 +393,10 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
// Exponential back-off.
timeoutMs = Math.min(timeoutMs*2, NETWORK_TIMEOUT_MS);
}
dumpOnFailure();
fail("Invalid state for expectAvailable=" + expectAvailable + " after " + maxTries
+ " attempts.\nLast error: " + error);
}
private void dumpOnFailure() throws Exception {
dumpAllNetworkRules();
Log.d(TAG, "Usagestats dump: " + getUsageStatsDump());
executeShellCommand("settings get global app_idle_constants");
}
private void dumpAllNetworkRules() throws Exception {
final String networkManagementDump = runShellCommand(mInstrumentation,
"dumpsys network_management").trim();
final String networkPolicyDump = runShellCommand(mInstrumentation,
"dumpsys netpolicy").trim();
TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter('\n');
splitter.setString(networkManagementDump);
String next;
Log.d(TAG, ">>> Begin network_management dump");
while (splitter.hasNext()) {
next = splitter.next();
Log.d(TAG, next);
}
Log.d(TAG, "<<< End network_management dump");
splitter.setString(networkPolicyDump);
Log.d(TAG, ">>> Begin netpolicy dump");
while (splitter.hasNext()) {
next = splitter.next();
Log.d(TAG, next);
}
Log.d(TAG, "<<< End netpolicy dump");
}
/**
* Checks whether the network is available as expected.
*
@@ -528,22 +448,10 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
return errors.toString();
}
protected boolean isLowRamDevice() {
final ActivityManager am = (ActivityManager) mContext.getSystemService(
Context.ACTIVITY_SERVICE);
return am.isLowRamDevice();
}
protected String executeShellCommand(String command) throws Exception {
final String result = runShellCommand(mInstrumentation, command).trim();
if (DEBUG) Log.d(TAG, "Command '" + command + "' returned '" + result + "'");
return result;
}
/**
* Runs a Shell command which is not expected to generate output.
*/
protected void executeSilentShellCommand(String command) throws Exception {
protected void executeSilentShellCommand(String command) {
final String result = executeShellCommand(command);
assertTrue("Command '" + command + "' failed: " + result, result.trim().isEmpty());
}
@@ -572,10 +480,6 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
});
}
protected void assertDelayedShellCommand(String command, ExpectResultChecker checker)
throws Exception {
assertDelayedShellCommand(command, 5, 1, checker);
}
protected void assertDelayedShellCommand(String command, int maxTries, int napTimeSeconds,
ExpectResultChecker checker) throws Exception {
String result = "";
@@ -592,159 +496,6 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
+ " attempts. Last result: '" + result + "'");
}
/**
* Sets the initial metering state for the active network.
*
* <p>It's called on setup and by default does nothing - it's up to the
* subclasses to override.
*
* @return whether the tests in the subclass are supported on this device.
*/
protected boolean setUpActiveNetworkMeteringState() throws Exception {
return true;
}
/**
* Makes sure the active network is not metered.
*
* <p>If the device does not supoprt un-metered networks (for example if it
* only has cellular data but not wi-fi), it should return {@code false};
* otherwise, it should return {@code true} (or fail if the un-metered
* network could not be set).
*
* @return {@code true} if the network is now unmetered.
*/
protected boolean setUnmeteredNetwork() throws Exception {
final NetworkInfo info = mCm.getActiveNetworkInfo();
assertNotNull("Could not get active network", info);
if (!mCm.isActiveNetworkMetered()) {
Log.d(TAG, "Active network is not metered: " + info);
} else if (info.getType() == ConnectivityManager.TYPE_WIFI) {
Log.i(TAG, "Setting active WI-FI network as not metered: " + info );
setWifiMeteredStatus(false);
} else {
Log.d(TAG, "Active network cannot be set to un-metered: " + info);
return false;
}
assertActiveNetworkMetered(false); // Sanity check.
return true;
}
/**
* Enables metering on the active network if supported.
*
* <p>If the device does not support metered networks it should return
* {@code false}; otherwise, it should return {@code true} (or fail if the
* metered network could not be set).
*
* @return {@code true} if the network is now metered.
*/
protected boolean setMeteredNetwork() throws Exception {
final NetworkInfo info = mCm.getActiveNetworkInfo();
final boolean metered = mCm.isActiveNetworkMetered();
if (metered) {
Log.d(TAG, "Active network already metered: " + info);
return true;
} else if (info.getType() != ConnectivityManager.TYPE_WIFI) {
Log.w(TAG, "Active network does not support metering: " + info);
return false;
} else {
Log.w(TAG, "Active network not metered: " + info);
}
final String netId = setWifiMeteredStatus(true);
// Set flag so status is reverted on resetMeteredNetwork();
mMeteredWifi = netId;
// Sanity check.
assertWifiMeteredStatus(netId, true);
assertActiveNetworkMetered(true);
return true;
}
/**
* Resets the device metering state to what it was before the test started.
*
* <p>This reverts any metering changes made by {@code setMeteredNetwork}.
*/
protected void resetMeteredNetwork() throws Exception {
if (mMeteredWifi != null) {
Log.i(TAG, "resetMeteredNetwork(): SID '" + mMeteredWifi
+ "' was set as metered by test case; resetting it");
setWifiMeteredStatus(mMeteredWifi, false);
assertActiveNetworkMetered(false); // Sanity check.
}
}
private void assertActiveNetworkMetered(boolean expected) throws Exception {
final int maxTries = 5;
NetworkInfo info = null;
for (int i = 1; i <= maxTries; i++) {
info = mCm.getActiveNetworkInfo();
if (info == null) {
Log.v(TAG, "No active network info on attempt #" + i
+ "; sleeping 1s before polling again");
} else if (mCm.isActiveNetworkMetered() != expected) {
Log.v(TAG, "Wrong metered status for active network " + info + "; expected="
+ expected + "; sleeping 1s before polling again");
} else {
break;
}
Thread.sleep(SECOND_IN_MS);
}
assertNotNull("No active network after " + maxTries + " attempts", info);
assertEquals("Wrong metered status for active network " + info, expected,
mCm.isActiveNetworkMetered());
}
private String setWifiMeteredStatus(boolean metered) throws Exception {
// We could call setWifiEnabled() here, but it might take sometime to be in a consistent
// state (for example, if one of the saved network is not properly authenticated), so it's
// better to let the hostside test take care of that.
assertTrue("wi-fi is disabled", mWfm.isWifiEnabled());
// TODO: if it's not guaranteed the device has wi-fi, we need to change the tests
// to make the actual verification of restrictions optional.
final String ssid = mWfm.getConnectionInfo().getSSID();
return setWifiMeteredStatus(ssid, metered);
}
private String setWifiMeteredStatus(String ssid, boolean metered) throws Exception {
assertNotNull("null SSID", ssid);
final String netId = ssid.trim().replaceAll("\"", ""); // remove quotes, if any.
assertFalse("empty SSID", ssid.isEmpty());
Log.i(TAG, "Setting wi-fi network " + netId + " metered status to " + metered);
final String setCommand = "cmd netpolicy set metered-network " + netId + " " + metered;
assertDelayedShellCommand(setCommand, "");
return netId;
}
private void assertWifiMeteredStatus(String netId, boolean status) throws Exception {
final String command = "cmd netpolicy list wifi-networks";
final String expectedLine = netId + ";" + status;
assertDelayedShellCommand(command, new ExpectResultChecker() {
@Override
public boolean isExpected(String result) {
return result.contains(expectedLine);
}
@Override
public String getExpected() {
return "line containing " + expectedLine;
}
});
}
protected void setRestrictBackground(boolean enabled) throws Exception {
executeShellCommand("cmd netpolicy set restrict-background " + enabled);
final String output = executeShellCommand("cmd netpolicy get restrict-background ");
final String expectedSuffix = enabled ? "enabled" : "disabled";
// TODO: use MoreAsserts?
assertTrue("output '" + output + "' should end with '" + expectedSuffix + "'",
output.endsWith(expectedSuffix));
}
protected void addRestrictBackgroundWhitelist(int uid) throws Exception {
executeShellCommand("cmd netpolicy add restrict-background-whitelist " + uid);
assertRestrictBackgroundWhitelist(uid, true);
@@ -924,7 +675,7 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
protected void setDozeMode(boolean enabled) throws Exception {
// Sanity check, since tests should check beforehand....
assertTrue("Device does not support Doze Mode", isDozeModeEnabled());
assertTrue("Device does not support Doze Mode", isDozeModeSupported());
Log.i(TAG, "Setting Doze Mode to " + enabled);
if (enabled) {
@@ -944,43 +695,16 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
assertDelayedShellCommand("dumpsys deviceidle get deep", enabled ? "IDLE" : "ACTIVE");
}
protected boolean isDozeModeEnabled() throws Exception {
final String result = executeShellCommand("cmd deviceidle enabled deep").trim();
return result.equals("1");
}
protected void setAppIdle(boolean enabled) throws Exception {
Log.i(TAG, "Setting app idle to " + enabled);
executeSilentShellCommand("am set-inactive " + TEST_APP2_PKG + " " + enabled );
assertAppIdle(enabled); // Sanity check
}
private String getUsageStatsDump() throws Exception {
final String output = runShellCommand(mInstrumentation, "dumpsys usagestats").trim();
final StringBuilder sb = new StringBuilder();
final TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter('\n');
splitter.setString(output);
String str;
while (splitter.hasNext()) {
str = splitter.next();
if (str.contains("package=")
&& !str.contains(TEST_PKG) && !str.contains(TEST_APP2_PKG)) {
continue;
}
if (str.trim().startsWith("config=") || str.trim().startsWith("time=")) {
continue;
}
sb.append(str).append('\n');
}
return sb.toString();
}
protected void assertAppIdle(boolean enabled) throws Exception {
try {
assertDelayedShellCommand("am get-inactive " + TEST_APP2_PKG, 15, 2, "Idle=" + enabled);
} catch (Throwable e) {
Log.d(TAG, "UsageStats dump:\n" + getUsageStatsDump());
executeShellCommand("settings get global app_idle_constants");
throw e;
}
}
@@ -1061,12 +785,10 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
// App didn't come to foreground when the activity is started, so try again.
assertForegroundNetworkAccess();
} else {
dumpOnFailure();
fail("Network is not available for app2 (" + mUid + "): " + errors[0]);
}
}
} else {
dumpOnFailure();
fail("Timed out waiting for network availability status from app2 (" + mUid + ")");
}
} else {
@@ -1150,19 +872,6 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
}
}
private String toString(int status) {
switch (status) {
case RESTRICT_BACKGROUND_STATUS_DISABLED:
return "DISABLED";
case RESTRICT_BACKGROUND_STATUS_WHITELISTED:
return "WHITELISTED";
case RESTRICT_BACKGROUND_STATUS_ENABLED:
return "ENABLED";
default:
return "UNKNOWN_STATUS_" + status;
}
}
private ProcessState getProcessStateByUid(int uid) throws Exception {
return new ProcessState(executeShellCommand("cmd activity get-uid-state " + uid));
}

View File

@@ -16,15 +16,8 @@
package com.android.cts.net.hostside;
import static com.android.cts.net.hostside.Property.METERED_NETWORK;
@RequiredProperties({METERED_NETWORK})
public class AppIdleMeteredTest extends AbstractAppIdleTestCase {
@Override
protected boolean setUpActiveNetworkMeteringState() throws Exception {
return setMeteredNetwork();
}
@Override
protected void tearDownMeteredNetwork() throws Exception {
resetMeteredNetwork();
}
}

View File

@@ -16,9 +16,8 @@
package com.android.cts.net.hostside;
import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK;
@RequiredProperties({NON_METERED_NETWORK})
public class AppIdleNonMeteredTest extends AbstractAppIdleTestCase {
@Override
protected boolean setUpActiveNetworkMeteringState() throws Exception {
return setUnmeteredNetwork();
}
}

View File

@@ -16,15 +16,8 @@
package com.android.cts.net.hostside;
import static com.android.cts.net.hostside.Property.METERED_NETWORK;
@RequiredProperties({METERED_NETWORK})
public class BatterySaverModeMeteredTest extends AbstractBatterySaverModeTestCase {
@Override
protected boolean setUpActiveNetworkMeteringState() throws Exception {
return setMeteredNetwork();
}
@Override
protected void tearDownMeteredNetwork() throws Exception {
resetMeteredNetwork();
}
}

View File

@@ -16,10 +16,9 @@
package com.android.cts.net.hostside;
public class BatterySaverModeNonMeteredTest extends AbstractBatterySaverModeTestCase {
@Override
protected boolean setUpActiveNetworkMeteringState() throws Exception {
return setUnmeteredNetwork();
}
import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK;
@RequiredProperties({NON_METERED_NETWORK})
public class BatterySaverModeNonMeteredTest extends AbstractBatterySaverModeTestCase {
}

View File

@@ -20,24 +20,33 @@ import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLE
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
import android.util.Log;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setRestrictBackground;
import static com.android.cts.net.hostside.Property.DATA_SAVER_MODE;
import static com.android.cts.net.hostside.Property.METERED_NETWORK;
import static com.android.cts.net.hostside.Property.NO_DATA_SAVER_MODE;
import static org.junit.Assert.fail;
import com.android.compatibility.common.util.CddTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import androidx.test.filters.LargeTest;
@RequiredProperties({DATA_SAVER_MODE, METERED_NETWORK})
@LargeTest
public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase {
private static final String[] REQUIRED_WHITELISTED_PACKAGES = {
"com.android.providers.downloads"
};
private boolean mIsDataSaverSupported;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
mIsDataSaverSupported = isDataSaverSupported();
// Set initial state.
setRestrictBackground(false);
removeRestrictBackgroundWhitelist(mUid);
@@ -47,36 +56,15 @@ public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase
assertRestrictBackgroundChangedReceived(0);
}
@Override
protected void tearDown() throws Exception {
@After
public void tearDown() throws Exception {
super.tearDown();
if (!isSupported()) return;
try {
resetMeteredNetwork();
} finally {
setRestrictBackground(false);
}
}
@Override
protected boolean setUpActiveNetworkMeteringState() throws Exception {
return setMeteredNetwork();
}
@Override
protected boolean isSupported() throws Exception {
if (!mIsDataSaverSupported) {
Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ "() because device does not support Data Saver Mode");
}
return mIsDataSaverSupported && super.isSupported();
setRestrictBackground(false);
}
@Test
public void testGetRestrictBackgroundStatus_disabled() throws Exception {
if (!isSupported()) return;
assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED);
// Sanity check: make sure status is always disabled, never whitelisted
@@ -88,9 +76,8 @@ public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase
assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED);
}
@Test
public void testGetRestrictBackgroundStatus_whitelisted() throws Exception {
if (!isSupported()) return;
setRestrictBackground(true);
assertRestrictBackgroundChangedReceived(1);
assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
@@ -107,9 +94,8 @@ public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase
assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
}
@Test
public void testGetRestrictBackgroundStatus_enabled() throws Exception {
if (!isSupported()) return;
setRestrictBackground(true);
assertRestrictBackgroundChangedReceived(1);
assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
@@ -142,9 +128,8 @@ public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase
assertBackgroundNetworkAccess(false);
}
@Test
public void testGetRestrictBackgroundStatus_blacklisted() throws Exception {
if (!isSupported()) return;
addRestrictBackgroundBlacklist(mUid);
assertRestrictBackgroundChangedReceived(1);
assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
@@ -180,9 +165,8 @@ public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase
assertsForegroundAlwaysHasNetworkAccess();
}
@Test
public void testGetRestrictBackgroundStatus_requiredWhitelistedPackages() throws Exception {
if (!isSupported()) return;
final StringBuilder error = new StringBuilder();
for (String packageName : REQUIRED_WHITELISTED_PACKAGES) {
int uid = -1;
@@ -202,10 +186,10 @@ public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase
}
}
@RequiredProperties({NO_DATA_SAVER_MODE})
@CddTest(requirement="7.4.7/C-2-2")
@Test
public void testBroadcastNotSentOnUnsupportedDevices() throws Exception {
if (isSupported()) return;
setRestrictBackground(true);
assertRestrictBackgroundChangedReceived(0);

View File

@@ -16,15 +16,8 @@
package com.android.cts.net.hostside;
import static com.android.cts.net.hostside.Property.METERED_NETWORK;
@RequiredProperties({METERED_NETWORK})
public class DozeModeMeteredTest extends AbstractDozeModeTestCase {
@Override
protected boolean setUpActiveNetworkMeteringState() throws Exception {
return setMeteredNetwork();
}
@Override
protected void tearDownMeteredNetwork() throws Exception {
resetMeteredNetwork();
}
}

View File

@@ -16,10 +16,8 @@
package com.android.cts.net.hostside;
public class DozeModeNonMeteredTest extends AbstractDozeModeTestCase {
import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK;
@Override
protected boolean setUpActiveNetworkMeteringState() throws Exception {
return setUnmeteredNetwork();
}
@RequiredProperties({NON_METERED_NETWORK})
public class DozeModeNonMeteredTest extends AbstractDozeModeTestCase {
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2019 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 com.android.cts.net.hostside;
import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TAG;
import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TEST_PKG;
import android.os.Environment;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import com.android.compatibility.common.util.OnFailureRule;
import org.junit.AssumptionViolatedException;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import androidx.test.platform.app.InstrumentationRegistry;
public class DumpOnFailureRule extends OnFailureRule {
private File mDumpDir = new File(Environment.getExternalStorageDirectory(),
"CtsHostsideNetworkTests");
@Override
public void onTestFailure(Statement base, Description description, Throwable throwable) {
final String testName = description.getClassName() + "_" + description.getMethodName();
if (throwable instanceof AssumptionViolatedException) {
Log.d(TAG, "Skipping test " + testName + ": " + throwable);
return;
}
prepareDumpRootDir();
final File dumpFile = new File(mDumpDir, "dump-" + testName);
Log.i(TAG, "Dumping debug info for " + description + ": " + dumpFile.getPath());
try (FileOutputStream out = new FileOutputStream(dumpFile)) {
for (String cmd : new String[] {
"dumpsys netpolicy",
"dumpsys network_management",
"dumpsys usagestats " + TEST_PKG,
"dumpsys usagestats appstandby",
}) {
dumpCommandOutput(out, cmd);
}
} catch (FileNotFoundException e) {
Log.e(TAG, "Error opening file: " + dumpFile, e);
} catch (IOException e) {
Log.e(TAG, "Error closing file: " + dumpFile, e);
}
}
void dumpCommandOutput(FileOutputStream out, String cmd) {
final ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation()
.getUiAutomation().executeShellCommand(cmd);
try (FileInputStream in = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
out.write(("Output of '" + cmd + "':\n").getBytes(StandardCharsets.UTF_8));
FileUtils.copy(in, out);
out.write("\n\n=================================================================\n\n"
.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
Log.e(TAG, "Error dumping '" + cmd + "'", e);
}
}
void prepareDumpRootDir() {
if (!mDumpDir.exists() && !mDumpDir.mkdir()) {
Log.e(TAG, "Error creating " + mDumpDir);
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2019 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 com.android.cts.net.hostside;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.resetMeteredNetwork;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setupMeteredNetwork;
import static com.android.cts.net.hostside.Property.METERED_NETWORK;
import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK;
import android.util.ArraySet;
import android.util.Pair;
import com.android.compatibility.common.util.BeforeAfterRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class MeterednessConfigurationRule extends BeforeAfterRule {
private Pair<String, Boolean> mSsidAndInitialMeteredness;
@Override
public void onBefore(Statement base, Description description) throws Throwable {
final ArraySet<Property> requiredProperties
= RequiredPropertiesRule.getRequiredProperties();
if (requiredProperties.contains(METERED_NETWORK)) {
configureNetworkMeteredness(true);
} else if (requiredProperties.contains(NON_METERED_NETWORK)) {
configureNetworkMeteredness(false);
}
}
@Override
public void onAfter(Statement base, Description description) throws Throwable {
resetNetworkMeteredness();
}
public void configureNetworkMeteredness(boolean metered) throws Exception {
mSsidAndInitialMeteredness = setupMeteredNetwork(metered);
}
public void resetNetworkMeteredness() throws Exception {
if (mSsidAndInitialMeteredness != null) {
resetMeteredNetwork(mSsidAndInitialMeteredness.first,
mSsidAndInitialMeteredness.second);
}
}
}

View File

@@ -15,9 +15,21 @@
*/
package com.android.cts.net.hostside;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setRestrictBackground;
import static com.android.cts.net.hostside.Property.APP_STANDBY_MODE;
import static com.android.cts.net.hostside.Property.BATTERY_SAVER_MODE;
import static com.android.cts.net.hostside.Property.DATA_SAVER_MODE;
import static com.android.cts.net.hostside.Property.DOZE_MODE;
import static com.android.cts.net.hostside.Property.METERED_NETWORK;
import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK;
import android.os.SystemClock;
import android.util.Log;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Test cases for the more complex scenarios where multiple restrictions (like Battery Saver Mode
* and Data Saver Mode) are applied simultaneously.
@@ -29,12 +41,10 @@ import android.util.Log;
public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
private static final String TAG = "MixedModesTest";
@Override
@Before
public void setUp() throws Exception {
super.setUp();
if (!isSupported()) return;
// Set initial state.
removeRestrictBackgroundWhitelist(mUid);
removeRestrictBackgroundBlacklist(mUid);
@@ -44,12 +54,10 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
registerBroadcastReceiver();
}
@Override
protected void tearDown() throws Exception {
@After
public void tearDown() throws Exception {
super.tearDown();
if (!isSupported()) return;
try {
setRestrictBackground(false);
} finally {
@@ -57,34 +65,15 @@ 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.
*/
@RequiredProperties({DATA_SAVER_MODE, BATTERY_SAVER_MODE, METERED_NETWORK})
@Test
public void testDataAndBatterySaverModes_meteredNetwork() throws Exception {
if (!isBatterySaverSupported()) {
Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ "() because device does not support Battery saver mode");
return;
}
if (!isSupported()) return;
Log.i(TAG, "testDataAndBatterySaverModes_meteredNetwork() tests");
if (!setMeteredNetwork()) {
Log.w(TAG, "testDataAndBatterySaverModes_meteredNetwork() skipped because "
+ "device cannot use a metered network");
return;
}
final MeterednessConfigurationRule meterednessConfiguration
= new MeterednessConfigurationRule();
meterednessConfiguration.configureNetworkMeteredness(true);
try {
setRestrictBackground(true);
setBatterySaverMode(true);
@@ -137,7 +126,7 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
removeRestrictBackgroundBlacklist(mUid);
removePowerSaveModeWhitelist(TEST_APP2_PKG);
} finally {
resetMeteredNetwork();
meterednessConfiguration.resetNetworkMeteredness();
}
}
@@ -145,86 +134,75 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
* Tests all DS ON and BS ON scenarios from network-policy-restrictions.md on non-metered
* networks.
*/
@RequiredProperties({DATA_SAVER_MODE, BATTERY_SAVER_MODE, NON_METERED_NETWORK})
@Test
public void testDataAndBatterySaverModes_nonMeteredNetwork() throws Exception {
if (!isBatterySaverSupported()) {
Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ "() because device does not support Battery saver mode");
return;
final MeterednessConfigurationRule meterednessConfiguration
= new MeterednessConfigurationRule();
meterednessConfiguration.configureNetworkMeteredness(false);
try {
setRestrictBackground(true);
setBatterySaverMode(true);
Log.v(TAG, "Not whitelisted for any.");
assertBackgroundNetworkAccess(false);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(false);
Log.v(TAG, "Whitelisted for Data Saver but not for Battery Saver.");
addRestrictBackgroundWhitelist(mUid);
removePowerSaveModeWhitelist(TEST_APP2_PKG);
assertBackgroundNetworkAccess(false);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(false);
removeRestrictBackgroundWhitelist(mUid);
Log.v(TAG, "Whitelisted for Battery Saver but not for Data Saver.");
addPowerSaveModeWhitelist(TEST_APP2_PKG);
removeRestrictBackgroundWhitelist(mUid);
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(true);
removePowerSaveModeWhitelist(TEST_APP2_PKG);
Log.v(TAG, "Whitelisted for both.");
addRestrictBackgroundWhitelist(mUid);
addPowerSaveModeWhitelist(TEST_APP2_PKG);
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(true);
removePowerSaveModeWhitelist(TEST_APP2_PKG);
assertBackgroundNetworkAccess(false);
removeRestrictBackgroundWhitelist(mUid);
Log.v(TAG, "Blacklisted for Data Saver, not whitelisted for Battery Saver.");
addRestrictBackgroundBlacklist(mUid);
removePowerSaveModeWhitelist(TEST_APP2_PKG);
assertBackgroundNetworkAccess(false);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(false);
removeRestrictBackgroundBlacklist(mUid);
Log.v(TAG, "Blacklisted for Data Saver, whitelisted for Battery Saver.");
addRestrictBackgroundBlacklist(mUid);
addPowerSaveModeWhitelist(TEST_APP2_PKG);
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(true);
removeRestrictBackgroundBlacklist(mUid);
removePowerSaveModeWhitelist(TEST_APP2_PKG);
} finally {
meterednessConfiguration.resetNetworkMeteredness();
}
if (!isSupported()) return;
if (!setUnmeteredNetwork()) {
Log.w(TAG, "testDataAndBatterySaverModes_nonMeteredNetwork() skipped because network"
+ " is metered");
return;
}
Log.i(TAG, "testDataAndBatterySaverModes_nonMeteredNetwork() tests");
setRestrictBackground(true);
setBatterySaverMode(true);
Log.v(TAG, "Not whitelisted for any.");
assertBackgroundNetworkAccess(false);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(false);
Log.v(TAG, "Whitelisted for Data Saver but not for Battery Saver.");
addRestrictBackgroundWhitelist(mUid);
removePowerSaveModeWhitelist(TEST_APP2_PKG);
assertBackgroundNetworkAccess(false);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(false);
removeRestrictBackgroundWhitelist(mUid);
Log.v(TAG, "Whitelisted for Battery Saver but not for Data Saver.");
addPowerSaveModeWhitelist(TEST_APP2_PKG);
removeRestrictBackgroundWhitelist(mUid);
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(true);
removePowerSaveModeWhitelist(TEST_APP2_PKG);
Log.v(TAG, "Whitelisted for both.");
addRestrictBackgroundWhitelist(mUid);
addPowerSaveModeWhitelist(TEST_APP2_PKG);
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(true);
removePowerSaveModeWhitelist(TEST_APP2_PKG);
assertBackgroundNetworkAccess(false);
removeRestrictBackgroundWhitelist(mUid);
Log.v(TAG, "Blacklisted for Data Saver, not whitelisted for Battery Saver.");
addRestrictBackgroundBlacklist(mUid);
removePowerSaveModeWhitelist(TEST_APP2_PKG);
assertBackgroundNetworkAccess(false);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(false);
removeRestrictBackgroundBlacklist(mUid);
Log.v(TAG, "Blacklisted for Data Saver, whitelisted for Battery Saver.");
addRestrictBackgroundBlacklist(mUid);
addPowerSaveModeWhitelist(TEST_APP2_PKG);
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();
assertBackgroundNetworkAccess(true);
removeRestrictBackgroundBlacklist(mUid);
removePowerSaveModeWhitelist(TEST_APP2_PKG);
}
/**
* Tests that powersave whitelists works as expected when doze and battery saver modes
* are enabled.
*/
@RequiredProperties({DOZE_MODE, BATTERY_SAVER_MODE})
@Test
public void testDozeAndBatterySaverMode_powerSaveWhitelists() throws Exception {
if (!isBatterySaverSupported()) {
Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ "() because device does not support Battery saver mode");
return;
}
if (!isSupported()) {
return;
}
setBatterySaverMode(true);
setDozeMode(true);
@@ -250,11 +228,9 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
* Tests that powersave whitelists works as expected when doze and appIdle modes
* are enabled.
*/
@RequiredProperties({DOZE_MODE, APP_STANDBY_MODE})
@Test
public void testDozeAndAppIdle_powerSaveWhitelists() throws Exception {
if (!isSupported()) {
return;
}
setDozeMode(true);
setAppIdle(true);
@@ -276,11 +252,9 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
}
}
@RequiredProperties({APP_STANDBY_MODE, DOZE_MODE})
@Test
public void testAppIdleAndDoze_tempPowerSaveWhitelists() throws Exception {
if (!isSupported()) {
return;
}
setDozeMode(true);
setAppIdle(true);
@@ -299,16 +273,9 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
}
}
@RequiredProperties({APP_STANDBY_MODE, BATTERY_SAVER_MODE})
@Test
public void testAppIdleAndBatterySaver_tempPowerSaveWhitelists() throws Exception {
if (!isBatterySaverSupported()) {
Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ "() because device does not support Battery saver mode");
return;
}
if (!isSupported()) {
return;
}
setBatterySaverMode(true);
setAppIdle(true);
@@ -330,11 +297,9 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
/**
* Tests that the app idle whitelist works as expected when doze and appIdle mode are enabled.
*/
@RequiredProperties({DOZE_MODE, APP_STANDBY_MODE})
@Test
public void testDozeAndAppIdle_appIdleWhitelist() throws Exception {
if (!isSupported()) {
return;
}
setDozeMode(true);
setAppIdle(true);
@@ -353,11 +318,9 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
}
}
@RequiredProperties({APP_STANDBY_MODE, DOZE_MODE})
@Test
public void testAppIdleAndDoze_tempPowerSaveAndAppIdleWhitelists() throws Exception {
if (!isSupported()) {
return;
}
setDozeMode(true);
setAppIdle(true);
@@ -380,16 +343,9 @@ public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
}
}
@RequiredProperties({APP_STANDBY_MODE, BATTERY_SAVER_MODE})
@Test
public void testAppIdleAndBatterySaver_tempPowerSaveAndAppIdleWhitelists() throws Exception {
if (!isBatterySaverSupported()) {
Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ "() because device does not support Battery saver mode");
return;
}
if (!isSupported()) {
return;
}
setBatterySaverMode(true);
setAppIdle(true);

View File

@@ -16,15 +16,26 @@
package com.android.cts.net.hostside;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setRestrictBackground;
import static com.android.cts.net.hostside.Property.BATTERY_SAVER_MODE;
import static com.android.cts.net.hostside.Property.DATA_SAVER_MODE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import android.net.Network;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.Objects;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class NetworkCallbackTest extends AbstractRestrictBackgroundNetworkTestCase {
private boolean mIsDataSaverSupported;
private Network mNetwork;
private final TestNetworkCallback mTestNetworkCallback = new TestNetworkCallback();
@@ -132,108 +143,122 @@ public class NetworkCallbackTest extends AbstractRestrictBackgroundNetworkTestCa
}
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
mIsDataSaverSupported = isDataSaverSupported();
mNetwork = mCm.getActiveNetwork();
// Set initial state.
setBatterySaverMode(false);
registerBroadcastReceiver();
if (!mIsDataSaverSupported) return;
setRestrictBackground(false);
removeRestrictBackgroundWhitelist(mUid);
removeRestrictBackgroundBlacklist(mUid);
assertRestrictBackgroundChangedReceived(0);
}
@Override
protected void tearDown() throws Exception {
@After
public void tearDown() throws Exception {
super.tearDown();
if (!mIsDataSaverSupported) return;
setRestrictBackground(false);
setBatterySaverMode(false);
}
@RequiredProperties({DATA_SAVER_MODE})
@Test
public void testOnBlockedStatusChanged_dataSaver() throws Exception {
// Initial state
setBatterySaverMode(false);
setRestrictBackground(false);
final MeterednessConfigurationRule meterednessConfiguration
= new MeterednessConfigurationRule();
meterednessConfiguration.configureNetworkMeteredness(true);
try {
resetMeteredNetwork();
// Register callback
registerNetworkCallback((INetworkCallback.Stub) mTestNetworkCallback);
mTestNetworkCallback.expectAvailableCallback(mNetwork);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
// Enable restrict background
setRestrictBackground(true);
assertBackgroundNetworkAccess(false);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
// Add to whitelist
addRestrictBackgroundWhitelist(mUid);
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
// Remove from whitelist
removeRestrictBackgroundWhitelist(mUid);
assertBackgroundNetworkAccess(false);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
} finally {
meterednessConfiguration.resetNetworkMeteredness();
}
// Set to non-metered network
meterednessConfiguration.configureNetworkMeteredness(false);
try {
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
// Disable restrict background, should not trigger callback
setRestrictBackground(false);
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.assertNoCallback();
} finally {
meterednessConfiguration.resetNetworkMeteredness();
}
}
public void testOnBlockedStatusChanged_data_saver() throws Exception {
if (!mIsDataSaverSupported) return;
// Prepare metered wifi
if (!setMeteredNetwork()) return;
// Register callback
registerNetworkCallback((INetworkCallback.Stub) mTestNetworkCallback);
mTestNetworkCallback.expectAvailableCallback(mNetwork);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
// Enable restrict background
setRestrictBackground(true);
assertBackgroundNetworkAccess(false);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
// Add to whitelist
addRestrictBackgroundWhitelist(mUid);
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
// Remove from whitelist
removeRestrictBackgroundWhitelist(mUid);
assertBackgroundNetworkAccess(false);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
// Set to non-metered network
setUnmeteredNetwork();
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
// Disable restrict background, should not trigger callback
@RequiredProperties({BATTERY_SAVER_MODE})
@Test
public void testOnBlockedStatusChanged_powerSaver() throws Exception {
// Set initial state.
setBatterySaverMode(false);
setRestrictBackground(false);
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.assertNoCallback();
}
final MeterednessConfigurationRule meterednessConfiguration
= new MeterednessConfigurationRule();
meterednessConfiguration.configureNetworkMeteredness(true);
try {
// Register callback
registerNetworkCallback((INetworkCallback.Stub) mTestNetworkCallback);
mTestNetworkCallback.expectAvailableCallback(mNetwork);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
public void testOnBlockedStatusChanged_power_saver() throws Exception {
// Prepare metered wifi
if (!setMeteredNetwork()) return;
// Enable Power Saver
setBatterySaverMode(true);
assertBackgroundNetworkAccess(false);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
// Register callback
registerNetworkCallback((INetworkCallback.Stub) mTestNetworkCallback);
mTestNetworkCallback.expectAvailableCallback(mNetwork);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
// Enable Power Saver
setBatterySaverMode(true);
assertBackgroundNetworkAccess(false);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
// Disable Power Saver
setBatterySaverMode(false);
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
// Disable Power Saver
setBatterySaverMode(false);
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
} finally {
meterednessConfiguration.resetNetworkMeteredness();
}
// Set to non-metered network
setUnmeteredNetwork();
mTestNetworkCallback.assertNoCallback();
meterednessConfiguration.configureNetworkMeteredness(false);
try {
mTestNetworkCallback.assertNoCallback();
// Enable Power Saver
setBatterySaverMode(true);
assertBackgroundNetworkAccess(false);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
// Enable Power Saver
setBatterySaverMode(true);
assertBackgroundNetworkAccess(false);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
// Disable Power Saver
setBatterySaverMode(false);
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
// Disable Power Saver
setBatterySaverMode(false);
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
} finally {
meterednessConfiguration.resetNetworkMeteredness();
}
}
// TODO: 1. test against VPN lockdown.

View File

@@ -0,0 +1,255 @@
/*
* Copyright (C) 2019 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 com.android.cts.net.hostside;
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.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TAG;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.wifi.WifiManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import com.android.compatibility.common.util.AppStandbyUtils;
import com.android.compatibility.common.util.BatteryUtils;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import androidx.test.platform.app.InstrumentationRegistry;
public class NetworkPolicyTestUtils {
private static final int TIMEOUT_CHANGE_METEREDNESS_MS = 5000;
private static ConnectivityManager mCm;
private static WifiManager mWm;
private static Boolean mBatterySaverSupported;
private static Boolean mDataSaverSupported;
private static Boolean mDozeModeSupported;
private static Boolean mAppStandbySupported;
private NetworkPolicyTestUtils() {}
public static boolean isBatterySaverSupported() {
if (mBatterySaverSupported == null) {
mBatterySaverSupported = BatteryUtils.isBatterySaverSupported();
}
return mBatterySaverSupported;
}
/**
* As per CDD requirements, if the device doesn't support data saver mode then
* ConnectivityManager.getRestrictBackgroundStatus() will always return
* RESTRICT_BACKGROUND_STATUS_DISABLED. So, enable the data saver mode and check if
* ConnectivityManager.getRestrictBackgroundStatus() for an app in background returns
* RESTRICT_BACKGROUND_STATUS_DISABLED or not.
*/
public static boolean isDataSaverSupported() {
if (mDataSaverSupported == null) {
assertMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
try {
setRestrictBackground(true);
mDataSaverSupported = !isMyRestrictBackgroundStatus(
RESTRICT_BACKGROUND_STATUS_DISABLED);
} finally {
setRestrictBackground(false);
}
}
return mDataSaverSupported;
}
public static boolean isDozeModeSupported() {
if (mDozeModeSupported == null) {
final String result = executeShellCommand("cmd deviceidle enabled deep");
mDozeModeSupported = result.equals("1");
}
return mDozeModeSupported;
}
public static boolean isAppStandbySupported() {
if (mAppStandbySupported == null) {
mAppStandbySupported = AppStandbyUtils.isAppStandbyEnabled();
}
return mAppStandbySupported;
}
public static boolean isLowRamDevice() {
final ActivityManager am = (ActivityManager) getContext().getSystemService(
Context.ACTIVITY_SERVICE);
return am.isLowRamDevice();
}
public static boolean isActiveNetworkMetered(boolean metered) {
return getConnectivityManager().isActiveNetworkMetered() == metered;
}
public static boolean canChangeActiveNetworkMeteredness() {
final Network activeNetwork = getConnectivityManager().getActiveNetwork();
final NetworkCapabilities networkCapabilities
= getConnectivityManager().getNetworkCapabilities(activeNetwork);
return networkCapabilities.hasTransport(TRANSPORT_WIFI);
}
public static Pair<String, Boolean> setupMeteredNetwork(boolean metered) throws Exception {
if (isActiveNetworkMetered(metered)) {
return null;
}
final String ssid = unquoteSSID(getWifiManager().getConnectionInfo().getSSID());
setWifiMeteredStatus(ssid, metered);
return Pair.create(ssid, !metered);
}
public static void resetMeteredNetwork(String ssid, boolean metered) throws Exception {
setWifiMeteredStatus(ssid, metered);
}
public static void setWifiMeteredStatus(String ssid, boolean metered) throws Exception {
assertFalse("SSID should not be empty", TextUtils.isEmpty(ssid));
final String cmd = "cmd netpolicy set metered-network " + ssid + " " + metered;
executeShellCommand(cmd);
assertWifiMeteredStatus(ssid, metered);
assertActiveNetworkMetered(metered);
}
public static void assertWifiMeteredStatus(String ssid, boolean expectedMeteredStatus) {
final String result = executeShellCommand("cmd netpolicy list wifi-networks");
final String expectedLine = ssid + ";" + expectedMeteredStatus;
assertTrue("Expected line: " + expectedLine + "; Actual result: " + result,
result.contains(expectedLine));
}
// Copied from cts/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
public static void assertActiveNetworkMetered(boolean expectedMeteredStatus) throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final NetworkCallback networkCallback = new NetworkCallback() {
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
final boolean metered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
if (metered == expectedMeteredStatus) {
latch.countDown();
}
}
};
// Registering a callback here guarantees onCapabilitiesChanged is called immediately
// with the current setting. Therefore, if the setting has already been changed,
// this method will return right away, and if not it will wait for the setting to change.
getConnectivityManager().registerDefaultNetworkCallback(networkCallback);
if (!latch.await(TIMEOUT_CHANGE_METEREDNESS_MS, TimeUnit.MILLISECONDS)) {
fail("Timed out waiting for active network metered status to change to "
+ expectedMeteredStatus + " ; network = "
+ getConnectivityManager().getActiveNetwork());
}
getConnectivityManager().unregisterNetworkCallback(networkCallback);
}
public static void setRestrictBackground(boolean enabled) {
executeShellCommand("cmd netpolicy set restrict-background " + enabled);
final String output = executeShellCommand("cmd netpolicy get restrict-background");
final String expectedSuffix = enabled ? "enabled" : "disabled";
assertTrue("output '" + output + "' should end with '" + expectedSuffix + "'",
output.endsWith(expectedSuffix));
}
public static boolean isMyRestrictBackgroundStatus(int expectedStatus) {
final int actualStatus = getConnectivityManager().getRestrictBackgroundStatus();
if (expectedStatus != actualStatus) {
Log.d(TAG, "MyRestrictBackgroundStatus: "
+ "Expected: " + restrictBackgroundValueToString(expectedStatus)
+ "; Actual: " + restrictBackgroundValueToString(actualStatus));
return false;
}
return true;
}
// Copied from cts/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
private static String unquoteSSID(String ssid) {
// SSID is returned surrounded by quotes if it can be decoded as UTF-8.
// Otherwise it's guaranteed not to start with a quote.
if (ssid.charAt(0) == '"') {
return ssid.substring(1, ssid.length() - 1);
} else {
return ssid;
}
}
public static String restrictBackgroundValueToString(int status) {
switch (status) {
case RESTRICT_BACKGROUND_STATUS_DISABLED:
return "DISABLED";
case RESTRICT_BACKGROUND_STATUS_WHITELISTED:
return "WHITELISTED";
case RESTRICT_BACKGROUND_STATUS_ENABLED:
return "ENABLED";
default:
return "UNKNOWN_STATUS_" + status;
}
}
public static String executeShellCommand(String command) {
final String result = runShellCommand(command).trim();
Log.d(TAG, "Output of '" + command + "': '" + result + "'");
return result;
}
public static void assertMyRestrictBackgroundStatus(int expectedStatus) {
final int actualStatus = getConnectivityManager().getRestrictBackgroundStatus();
assertEquals(restrictBackgroundValueToString(expectedStatus),
restrictBackgroundValueToString(actualStatus));
}
public static ConnectivityManager getConnectivityManager() {
if (mCm == null) {
mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
}
return mCm;
}
public static WifiManager getWifiManager() {
if (mWm == null) {
mWm = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
}
return mWm;
}
public static Context getContext() {
return getInstrumentation().getContext();
}
public static Instrumentation getInstrumentation() {
return InstrumentationRegistry.getInstrumentation();
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2019 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 com.android.cts.net.hostside;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.canChangeActiveNetworkMeteredness;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isActiveNetworkMetered;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isAppStandbySupported;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isBatterySaverSupported;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isDataSaverSupported;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isDozeModeSupported;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isLowRamDevice;
public enum Property {
BATTERY_SAVER_MODE(1 << 0) {
public boolean isSupported() { return isBatterySaverSupported(); }
},
DATA_SAVER_MODE(1 << 1) {
public boolean isSupported() { return isDataSaverSupported(); }
},
NO_DATA_SAVER_MODE(~DATA_SAVER_MODE.getValue()) {
public boolean isSupported() { return !isDataSaverSupported(); }
},
DOZE_MODE(1 << 2) {
public boolean isSupported() { return isDozeModeSupported(); }
},
APP_STANDBY_MODE(1 << 3) {
public boolean isSupported() { return isAppStandbySupported(); }
},
NOT_LOW_RAM_DEVICE(1 << 4) {
public boolean isSupported() { return !isLowRamDevice(); }
},
METERED_NETWORK(1 << 5) {
public boolean isSupported() {
return isActiveNetworkMetered(true) || canChangeActiveNetworkMeteredness();
}
},
NON_METERED_NETWORK(~METERED_NETWORK.getValue()) {
public boolean isSupported() {
return isActiveNetworkMetered(false) || canChangeActiveNetworkMeteredness();
}
};
private int mValue;
Property(int value) { mValue = value; }
public int getValue() { return mValue; }
abstract boolean isSupported();
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2019 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 com.android.cts.net.hostside;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target({METHOD, TYPE})
@Inherited
public @interface RequiredProperties {
Property[] value();
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) 2019 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 com.android.cts.net.hostside;
import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TAG;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import com.android.compatibility.common.util.BeforeAfterRule;
import org.junit.Assume;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import java.util.ArrayList;
import java.util.Collections;
public class RequiredPropertiesRule extends BeforeAfterRule {
private static ArraySet<Property> mRequiredProperties;
@Override
public void onBefore(Statement base, Description description) {
mRequiredProperties = getAllRequiredProperties(description);
final String testName = description.getClassName() + "#" + description.getMethodName();
assertTestIsValid(testName, mRequiredProperties);
Log.i(TAG, "Running test " + testName + " with required properties: "
+ propertiesToString(mRequiredProperties));
}
private ArraySet<Property> getAllRequiredProperties(Description description) {
final ArraySet<Property> allRequiredProperties = new ArraySet<>();
RequiredProperties requiredProperties = description.getAnnotation(RequiredProperties.class);
if (requiredProperties != null) {
Collections.addAll(allRequiredProperties, requiredProperties.value());
}
for (Class<?> clazz = description.getTestClass();
clazz != null; clazz = clazz.getSuperclass()) {
requiredProperties = clazz.getDeclaredAnnotation(RequiredProperties.class);
if (requiredProperties == null) {
continue;
}
for (Property requiredProperty : requiredProperties.value()) {
if (!allRequiredProperties.contains(~requiredProperty.getValue())) {
allRequiredProperties.add(requiredProperty);
}
}
}
return allRequiredProperties;
}
private void assertTestIsValid(String testName, ArraySet<Property> requiredProperies) {
if (requiredProperies == null) {
return;
}
final ArrayList<Property> unsupportedProperties = new ArrayList<>();
for (Property property : requiredProperies) {
if (!property.isSupported()) {
unsupportedProperties.add(property);
}
}
Assume.assumeTrue("Unsupported properties: "
+ propertiesToString(unsupportedProperties), unsupportedProperties.isEmpty());
}
public static ArraySet<Property> getRequiredProperties() {
return mRequiredProperties;
}
private static String propertiesToString(Iterable<Property> properties) {
return "[" + TextUtils.join(",", properties) + "]";
}
}

View File

@@ -29,14 +29,14 @@ public class HostsideNetworkCallbackTests extends HostsideNetworkTestCase {
uninstallPackage(TEST_APP2_PKG, true);
}
public void testOnBlockedStatusChanged_data_saver() throws Exception {
public void testOnBlockedStatusChanged_dataSaver() throws Exception {
runDeviceTests(TEST_PKG,
TEST_PKG + ".NetworkCallbackTest", "testOnBlockedStatusChanged_data_saver");
TEST_PKG + ".NetworkCallbackTest", "testOnBlockedStatusChanged_dataSaver");
}
public void testOnBlockedStatusChanged_power_saver() throws Exception {
public void testOnBlockedStatusChanged_powerSaver() throws Exception {
runDeviceTests(TEST_PKG,
TEST_PKG + ".NetworkCallbackTest", "testOnBlockedStatusChanged_power_saver");
TEST_PKG + ".NetworkCallbackTest", "testOnBlockedStatusChanged_powerSaver");
}
}

View File

@@ -79,7 +79,8 @@ abstract class HostsideNetworkTestCase extends DeviceTestCase implements IAbiRec
protected void installPackage(String apk) throws FileNotFoundException,
DeviceNotAvailableException {
CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
assertNull(getDevice().installPackage(buildHelper.getTestFile(apk), false));
assertNull(getDevice().installPackage(buildHelper.getTestFile(apk),
false /* reinstall */, true /* grantPermissions */));
}
protected void uninstallPackage(String packageName, boolean shouldSucceed)