Merge "Verify apps cannot receive ACTION_SNOOZE_WARNING broadcast." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
69fbdff0ed
@@ -29,5 +29,6 @@ java_test_host {
|
|||||||
test_suites: [
|
test_suites: [
|
||||||
"cts",
|
"cts",
|
||||||
"general-tests",
|
"general-tests",
|
||||||
|
"sts"
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,14 +26,15 @@ android_test_helper_app {
|
|||||||
],
|
],
|
||||||
platform_apis: true,
|
platform_apis: true,
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"androidx.test.rules",
|
"CtsHostsideNetworkTestsAidl",
|
||||||
"androidx.test.ext.junit",
|
"androidx.test.ext.junit",
|
||||||
|
"androidx.test.rules",
|
||||||
|
"androidx.test.uiautomator_uiautomator",
|
||||||
"compatibility-device-util-axt",
|
"compatibility-device-util-axt",
|
||||||
"cts-net-utils",
|
"cts-net-utils",
|
||||||
"ctstestrunner-axt",
|
"ctstestrunner-axt",
|
||||||
"ub-uiautomator",
|
|
||||||
"CtsHostsideNetworkTestsAidl",
|
|
||||||
"modules-utils-build",
|
"modules-utils-build",
|
||||||
|
"ub-uiautomator",
|
||||||
],
|
],
|
||||||
libs: [
|
libs: [
|
||||||
"android.test.runner",
|
"android.test.runner",
|
||||||
|
|||||||
@@ -99,6 +99,9 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase {
|
|||||||
"com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY";
|
"com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY";
|
||||||
private static final String ACTION_FINISH_JOB =
|
private static final String ACTION_FINISH_JOB =
|
||||||
"com.android.cts.net.hostside.app2.action.FINISH_JOB";
|
"com.android.cts.net.hostside.app2.action.FINISH_JOB";
|
||||||
|
// Copied from com.android.server.net.NetworkPolicyManagerService class
|
||||||
|
private static final String ACTION_SNOOZE_WARNING =
|
||||||
|
"com.android.server.net.action.SNOOZE_WARNING";
|
||||||
|
|
||||||
private static final String ACTION_RECEIVER_READY =
|
private static final String ACTION_RECEIVER_READY =
|
||||||
"com.android.cts.net.hostside.app2.action.RECEIVER_READY";
|
"com.android.cts.net.hostside.app2.action.RECEIVER_READY";
|
||||||
@@ -148,6 +151,8 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase {
|
|||||||
|
|
||||||
protected static final long TEMP_POWERSAVE_WHITELIST_DURATION_MS = 5_000; // 5 sec
|
protected static final long TEMP_POWERSAVE_WHITELIST_DURATION_MS = 5_000; // 5 sec
|
||||||
|
|
||||||
|
private static final long BROADCAST_TIMEOUT_MS = 15_000;
|
||||||
|
|
||||||
protected Context mContext;
|
protected Context mContext;
|
||||||
protected Instrumentation mInstrumentation;
|
protected Instrumentation mInstrumentation;
|
||||||
protected ConnectivityManager mCm;
|
protected ConnectivityManager mCm;
|
||||||
@@ -217,6 +222,12 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase {
|
|||||||
+ maxAttempts * SLEEP_TIME_SEC + " seconds", expectedCount, count);
|
+ maxAttempts * SLEEP_TIME_SEC + " seconds", expectedCount, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void assertSnoozeWarningNotReceived() throws Exception {
|
||||||
|
// Wait for a while to take broadcast queue delays into account
|
||||||
|
SystemClock.sleep(BROADCAST_TIMEOUT_MS);
|
||||||
|
assertEquals(0, getNumberBroadcastsReceived(DYNAMIC_RECEIVER, ACTION_SNOOZE_WARNING));
|
||||||
|
}
|
||||||
|
|
||||||
protected String sendOrderedBroadcast(Intent intent) throws Exception {
|
protected String sendOrderedBroadcast(Intent intent) throws Exception {
|
||||||
return sendOrderedBroadcast(intent, ORDERED_BROADCAST_TIMEOUT_MS);
|
return sendOrderedBroadcast(intent, ORDERED_BROADCAST_TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.clearSnoozeTimestamps;
|
||||||
|
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.support.test.uiautomator.By;
|
||||||
|
import android.support.test.uiautomator.Direction;
|
||||||
|
import android.support.test.uiautomator.UiObject2;
|
||||||
|
import android.support.test.uiautomator.Until;
|
||||||
|
import android.telephony.SubscriptionManager;
|
||||||
|
import android.telephony.SubscriptionPlan;
|
||||||
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import androidx.test.uiautomator.UiDevice;
|
||||||
|
|
||||||
|
import com.android.compatibility.common.util.SystemUtil;
|
||||||
|
import com.android.compatibility.common.util.UiAutomatorUtils;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assume;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.time.Period;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DataWarningReceiverTest extends AbstractRestrictBackgroundNetworkTestCase {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
clearSnoozeTimestamps();
|
||||||
|
registerBroadcastReceiver();
|
||||||
|
turnScreenOn();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSnoozeWarningNotReceived() throws Exception {
|
||||||
|
Assume.assumeTrue("Feature not supported: " + PackageManager.FEATURE_TELEPHONY,
|
||||||
|
mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
|
||||||
|
final SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class);
|
||||||
|
final int subId = SubscriptionManager.getDefaultDataSubscriptionId();
|
||||||
|
Assume.assumeTrue("Valid subId not found",
|
||||||
|
subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||||
|
|
||||||
|
setSubPlanOwner(subId, TEST_PKG);
|
||||||
|
final List<SubscriptionPlan> originalPlans = sm.getSubscriptionPlans(subId);
|
||||||
|
try {
|
||||||
|
// In NetworkPolicyManagerService class, we set the data warning bytes to 90% of
|
||||||
|
// data limit bytes. So, create the subscription plan in such a way this data warning
|
||||||
|
// threshold is already reached.
|
||||||
|
final SubscriptionPlan plan = SubscriptionPlan.Builder
|
||||||
|
.createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"),
|
||||||
|
Period.ofMonths(1))
|
||||||
|
.setTitle("CTS")
|
||||||
|
.setDataLimit(1_000_000_000, SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
|
||||||
|
.setDataUsage(999_000_000, System.currentTimeMillis())
|
||||||
|
.build();
|
||||||
|
sm.setSubscriptionPlans(subId, Arrays.asList(plan));
|
||||||
|
final UiDevice uiDevice = UiDevice.getInstance(mInstrumentation);
|
||||||
|
uiDevice.openNotification();
|
||||||
|
try {
|
||||||
|
final UiObject2 uiObject = UiAutomatorUtils.waitFindObject(
|
||||||
|
By.text("Data warning"));
|
||||||
|
Assume.assumeNotNull(uiObject);
|
||||||
|
uiObject.wait(Until.clickable(true), 10_000L);
|
||||||
|
uiObject.getParent().swipe(Direction.RIGHT, 1.0f);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Assume.assumeNoException(
|
||||||
|
"Error occurred while finding and swiping the notification", t);
|
||||||
|
}
|
||||||
|
assertSnoozeWarningNotReceived();
|
||||||
|
uiDevice.pressHome();
|
||||||
|
} finally {
|
||||||
|
sm.setSubscriptionPlans(subId, originalPlans);
|
||||||
|
setSubPlanOwner(subId, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setSubPlanOwner(int subId, String packageName) throws Exception {
|
||||||
|
SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
|
||||||
|
"cmd netpolicy set sub-plan-owner " + subId + " " + packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ import android.os.ParcelFileDescriptor;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry;
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import androidx.test.uiautomator.UiDevice;
|
||||||
|
|
||||||
import com.android.compatibility.common.util.OnFailureRule;
|
import com.android.compatibility.common.util.OnFailureRule;
|
||||||
|
|
||||||
@@ -52,7 +53,8 @@ public class DumpOnFailureRule extends OnFailureRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prepareDumpRootDir();
|
prepareDumpRootDir();
|
||||||
final File dumpFile = new File(mDumpDir, "dump-" + getShortenedTestName(description));
|
final String shortenedTestName = getShortenedTestName(description);
|
||||||
|
final File dumpFile = new File(mDumpDir, "dump-" + shortenedTestName);
|
||||||
Log.i(TAG, "Dumping debug info for " + description + ": " + dumpFile.getPath());
|
Log.i(TAG, "Dumping debug info for " + description + ": " + dumpFile.getPath());
|
||||||
try (FileOutputStream out = new FileOutputStream(dumpFile)) {
|
try (FileOutputStream out = new FileOutputStream(dumpFile)) {
|
||||||
for (String cmd : new String[] {
|
for (String cmd : new String[] {
|
||||||
@@ -68,6 +70,16 @@ public class DumpOnFailureRule extends OnFailureRule {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Error closing file: " + dumpFile, e);
|
Log.e(TAG, "Error closing file: " + dumpFile, e);
|
||||||
}
|
}
|
||||||
|
final UiDevice uiDevice = UiDevice.getInstance(
|
||||||
|
InstrumentationRegistry.getInstrumentation());
|
||||||
|
final File screenshotFile = new File(mDumpDir, "sc-" + shortenedTestName + ".png");
|
||||||
|
uiDevice.takeScreenshot(screenshotFile);
|
||||||
|
final File windowHierarchyFile = new File(mDumpDir, "wh-" + shortenedTestName + ".xml");
|
||||||
|
try {
|
||||||
|
uiDevice.dumpWindowHierarchy(windowHierarchyFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Error dumping window hierarchy", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getShortenedTestName(Description description) {
|
private String getShortenedTestName(Description description) {
|
||||||
|
|||||||
@@ -377,6 +377,10 @@ public class NetworkPolicyTestUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void clearSnoozeTimestamps() {
|
||||||
|
executeShellCommand("dumpsys netpolicy --unsnooze");
|
||||||
|
}
|
||||||
|
|
||||||
public static String executeShellCommand(String command) {
|
public static String executeShellCommand(String command) {
|
||||||
final String result = runShellCommand(command).trim();
|
final String result = runShellCommand(command).trim();
|
||||||
Log.d(TAG, "Output of '" + command + "': '" + result + "'");
|
Log.d(TAG, "Output of '" + command + "': '" + result + "'");
|
||||||
|
|||||||
@@ -63,4 +63,12 @@
|
|||||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Adding this to make sure that receiving the broadcast is not restricted by
|
||||||
|
package visibility restrictions.
|
||||||
|
-->
|
||||||
|
<queries>
|
||||||
|
<package android:name="android" />
|
||||||
|
</queries>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ public final class Common {
|
|||||||
"com.android.cts.net.hostside.app2.action.FINISH_JOB";
|
"com.android.cts.net.hostside.app2.action.FINISH_JOB";
|
||||||
static final String ACTION_SHOW_TOAST =
|
static final String ACTION_SHOW_TOAST =
|
||||||
"com.android.cts.net.hostside.app2.action.SHOW_TOAST";
|
"com.android.cts.net.hostside.app2.action.SHOW_TOAST";
|
||||||
|
// Copied from com.android.server.net.NetworkPolicyManagerService class
|
||||||
|
static final String ACTION_SNOOZE_WARNING =
|
||||||
|
"com.android.server.net.action.SNOOZE_WARNING";
|
||||||
|
|
||||||
static final String NOTIFICATION_TYPE_CONTENT = "CONTENT";
|
static final String NOTIFICATION_TYPE_CONTENT = "CONTENT";
|
||||||
static final String NOTIFICATION_TYPE_DELETE = "DELETE";
|
static final String NOTIFICATION_TYPE_DELETE = "DELETE";
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED
|
|||||||
|
|
||||||
import static com.android.cts.net.hostside.app2.Common.ACTION_RECEIVER_READY;
|
import static com.android.cts.net.hostside.app2.Common.ACTION_RECEIVER_READY;
|
||||||
import static com.android.cts.net.hostside.app2.Common.ACTION_SHOW_TOAST;
|
import static com.android.cts.net.hostside.app2.Common.ACTION_SHOW_TOAST;
|
||||||
|
import static com.android.cts.net.hostside.app2.Common.ACTION_SNOOZE_WARNING;
|
||||||
import static com.android.cts.net.hostside.app2.Common.MANIFEST_RECEIVER;
|
import static com.android.cts.net.hostside.app2.Common.MANIFEST_RECEIVER;
|
||||||
import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_ACTION;
|
import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_ACTION;
|
||||||
import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_ACTION_BUNDLE;
|
import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_ACTION_BUNDLE;
|
||||||
@@ -76,6 +77,9 @@ public class MyBroadcastReceiver extends BroadcastReceiver {
|
|||||||
Log.d(TAG, "onReceive() for " + mName + ": " + intent);
|
Log.d(TAG, "onReceive() for " + mName + ": " + intent);
|
||||||
final String action = intent.getAction();
|
final String action = intent.getAction();
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
case ACTION_SNOOZE_WARNING:
|
||||||
|
increaseCounter(context, action);
|
||||||
|
break;
|
||||||
case ACTION_RESTRICT_BACKGROUND_CHANGED:
|
case ACTION_RESTRICT_BACKGROUND_CHANGED:
|
||||||
increaseCounter(context, action);
|
increaseCounter(context, action);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.cts.net.hostside.app2;
|
|||||||
import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
|
import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
|
||||||
|
|
||||||
import static com.android.cts.net.hostside.app2.Common.ACTION_RECEIVER_READY;
|
import static com.android.cts.net.hostside.app2.Common.ACTION_RECEIVER_READY;
|
||||||
|
import static com.android.cts.net.hostside.app2.Common.ACTION_SNOOZE_WARNING;
|
||||||
import static com.android.cts.net.hostside.app2.Common.DYNAMIC_RECEIVER;
|
import static com.android.cts.net.hostside.app2.Common.DYNAMIC_RECEIVER;
|
||||||
import static com.android.cts.net.hostside.app2.Common.TAG;
|
import static com.android.cts.net.hostside.app2.Common.TAG;
|
||||||
|
|
||||||
@@ -67,6 +68,7 @@ public class MyService extends Service {
|
|||||||
context.registerReceiver(mReceiver, new IntentFilter(ACTION_RECEIVER_READY));
|
context.registerReceiver(mReceiver, new IntentFilter(ACTION_RECEIVER_READY));
|
||||||
context.registerReceiver(mReceiver,
|
context.registerReceiver(mReceiver,
|
||||||
new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED));
|
new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED));
|
||||||
|
context.registerReceiver(mReceiver, new IntentFilter(ACTION_SNOOZE_WARNING));
|
||||||
Log.d(TAG, "receiver registered");
|
Log.d(TAG, "receiver registered");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.cts.net;
|
package com.android.cts.net;
|
||||||
|
|
||||||
import android.platform.test.annotations.FlakyTest;
|
import android.platform.test.annotations.FlakyTest;
|
||||||
|
import android.platform.test.annotations.SecurityTest;
|
||||||
|
|
||||||
import com.android.ddmlib.Log;
|
import com.android.ddmlib.Log;
|
||||||
import com.android.tradefed.device.DeviceNotAvailableException;
|
import com.android.tradefed.device.DeviceNotAvailableException;
|
||||||
@@ -38,6 +39,12 @@ public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestC
|
|||||||
uninstallPackage(TEST_APP2_PKG, true);
|
uninstallPackage(TEST_APP2_PKG, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SecurityTest
|
||||||
|
public void testDataWarningReceiver() throws Exception {
|
||||||
|
runDeviceTests(TEST_PKG, TEST_PKG + ".DataWarningReceiverTest",
|
||||||
|
"testSnoozeWarningNotReceived");
|
||||||
|
}
|
||||||
|
|
||||||
/**************************
|
/**************************
|
||||||
* Data Saver Mode tests. *
|
* Data Saver Mode tests. *
|
||||||
**************************/
|
**************************/
|
||||||
|
|||||||
Reference in New Issue
Block a user