Merge "Verify apps cannot receive ACTION_SNOOZE_WARNING broadcast." into sc-dev
diff --git a/tests/cts/hostside/Android.bp b/tests/cts/hostside/Android.bp
index 3185f7e..f72a458 100644
--- a/tests/cts/hostside/Android.bp
+++ b/tests/cts/hostside/Android.bp
@@ -29,5 +29,6 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts"
     ],
 }
diff --git a/tests/cts/hostside/app/Android.bp b/tests/cts/hostside/app/Android.bp
index 5b2369c..674af14 100644
--- a/tests/cts/hostside/app/Android.bp
+++ b/tests/cts/hostside/app/Android.bp
@@ -26,14 +26,15 @@
     ],
     platform_apis: true,
     static_libs: [
-        "androidx.test.rules",
+        "CtsHostsideNetworkTestsAidl",
         "androidx.test.ext.junit",
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
         "compatibility-device-util-axt",
         "cts-net-utils",
         "ctstestrunner-axt",
-        "ub-uiautomator",
-        "CtsHostsideNetworkTestsAidl",
         "modules-utils-build",
+        "ub-uiautomator",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 5b88f1b..1b52ec4 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -99,6 +99,9 @@
             "com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY";
     private static final String 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 =
             "com.android.cts.net.hostside.app2.action.RECEIVER_READY";
@@ -148,6 +151,8 @@
 
     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 Instrumentation mInstrumentation;
     protected ConnectivityManager mCm;
@@ -217,6 +222,12 @@
                 + 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 {
         return sendOrderedBroadcast(intent, ORDERED_BROADCAST_TIMEOUT_MS);
     }
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataWarningReceiverTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataWarningReceiverTest.java
new file mode 100644
index 0000000..b2e81ff
--- /dev/null
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataWarningReceiverTest.java
@@ -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);
+    }
+}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java
index 66cb935..cb0341c 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java
@@ -25,6 +25,7 @@
 import android.util.Log;
 
 import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
 
 import com.android.compatibility.common.util.OnFailureRule;
 
@@ -52,7 +53,8 @@
         }
 
         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());
         try (FileOutputStream out = new FileOutputStream(dumpFile)) {
             for (String cmd : new String[] {
@@ -68,6 +70,16 @@
         } catch (IOException 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) {
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java
index 4f9ce7c..89a9bd6 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java
@@ -377,6 +377,10 @@
         }
     }
 
+    public static void clearSnoozeTimestamps() {
+        executeShellCommand("dumpsys netpolicy --unsnooze");
+    }
+
     public static String executeShellCommand(String command) {
         final String result = runShellCommand(command).trim();
         Log.d(TAG, "Output of '" + command + "': '" + result + "'");
diff --git a/tests/cts/hostside/app2/AndroidManifest.xml b/tests/cts/hostside/app2/AndroidManifest.xml
index 4ac4bcb..6c9b469 100644
--- a/tests/cts/hostside/app2/AndroidManifest.xml
+++ b/tests/cts/hostside/app2/AndroidManifest.xml
@@ -63,4 +63,12 @@
             android:permission="android.permission.BIND_JOB_SERVICE" />
     </application>
 
+    <!--
+      Adding this to make sure that receiving the broadcast is not restricted by
+      package visibility restrictions.
+    -->
+    <queries>
+        <package android:name="android" />
+    </queries>
+
 </manifest>
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java
index 62b508c..2e79182 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java
@@ -44,6 +44,9 @@
             "com.android.cts.net.hostside.app2.action.FINISH_JOB";
     static final String 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_DELETE = "DELETE";
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
index c9ae16f..771b404 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
@@ -20,6 +20,7 @@
 
 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_SNOOZE_WARNING;
 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_BUNDLE;
@@ -76,6 +77,9 @@
         Log.d(TAG, "onReceive() for " + mName + ": " + intent);
         final String action = intent.getAction();
         switch (action) {
+            case ACTION_SNOOZE_WARNING:
+                increaseCounter(context, action);
+                break;
             case ACTION_RESTRICT_BACKGROUND_CHANGED:
                 increaseCounter(context, action);
                 break;
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
index 7dc4b9c..3b5e46f 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
@@ -18,6 +18,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_SNOOZE_WARNING;
 import static com.android.cts.net.hostside.app2.Common.DYNAMIC_RECEIVER;
 import static com.android.cts.net.hostside.app2.Common.TAG;
 
@@ -67,6 +68,7 @@
             context.registerReceiver(mReceiver, new IntentFilter(ACTION_RECEIVER_READY));
             context.registerReceiver(mReceiver,
                     new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED));
+            context.registerReceiver(mReceiver, new IntentFilter(ACTION_SNOOZE_WARNING));
             Log.d(TAG, "receiver registered");
         }
 
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
index d026fe0..a95fc64 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
@@ -17,6 +17,7 @@
 package com.android.cts.net;
 
 import android.platform.test.annotations.FlakyTest;
+import android.platform.test.annotations.SecurityTest;
 
 import com.android.ddmlib.Log;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -38,6 +39,12 @@
         uninstallPackage(TEST_APP2_PKG, true);
     }
 
+    @SecurityTest
+    public void testDataWarningReceiver() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".DataWarningReceiverTest",
+                "testSnoozeWarningNotReceived");
+    }
+
     /**************************
      * Data Saver Mode tests. *
      **************************/