Tests for app idle whitelisting.

Ensuring that app idle network whitelisting works as expected and does
not override other power saving restrictions.

Bug: 117846754
Bug: 111423978
Test: atest CtsHostsideNetworkTests
and atest NetworkPolicyManagerServiceTest
Change-Id: I09172184e2fe543d6723639e5e62ae6afd5a6087
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
index 0e141c0..7bf7bd4 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
@@ -175,6 +175,25 @@
         assertBackgroundNetworkAccess(true);
     }
 
+    public void testAppIdleNetworkAccess_idleWhitelisted() throws Exception {
+        if (!isSupported()) return;
+
+        setAppIdle(true);
+        assertAppIdle(true);
+        assertBackgroundNetworkAccess(false);
+
+        addAppIdleWhitelist(mUid);
+        assertBackgroundNetworkAccess(true);
+
+        removeAppIdleWhitelist(mUid);
+        assertBackgroundNetworkAccess(false);
+
+        // Make sure whitelisting a random app doesn't affect the tested app.
+        addAppIdleWhitelist(mUid + 1);
+        assertBackgroundNetworkAccess(false);
+        removeAppIdleWhitelist(mUid + 1);
+    }
+
     public void testAppIdle_toast() throws Exception {
         if (!isSupported()) return;
 
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 5232372..ec5a877 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
@@ -26,10 +26,6 @@
 
 import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
 
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
 import android.app.ActivityManager;
 import android.app.Instrumentation;
 import android.app.NotificationManager;
@@ -53,6 +49,10 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
 /**
  * Superclass for tests related to background network restrictions.
  */
@@ -744,6 +744,20 @@
         assertRestrictBackground("restrict-background-blacklist", uid, expected);
     }
 
+    protected void addAppIdleWhitelist(int uid) throws Exception {
+        executeShellCommand("cmd netpolicy add app-idle-whitelist " + uid);
+        assertAppIdleWhitelist(uid, true);
+    }
+
+    protected void removeAppIdleWhitelist(int uid) throws Exception {
+        executeShellCommand("cmd netpolicy remove app-idle-whitelist " + uid);
+        assertAppIdleWhitelist(uid, false);
+    }
+
+    protected void assertAppIdleWhitelist(int uid, boolean expected) throws Exception {
+        assertRestrictBackground("app-idle-whitelist", uid, expected);
+    }
+
     private void assertRestrictBackground(String list, int uid, boolean expected) throws Exception {
         final int maxTries = 5;
         boolean actual = false;
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java
index 87f9d77..74875cd 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java
@@ -306,4 +306,84 @@
             setBatterySaverMode(false);
         }
     }
+
+    /**
+     * Tests that the app idle whitelist works as expected when doze and appIdle mode are enabled.
+     */
+    public void testDozeAndAppIdle_appIdleWhitelist() throws Exception {
+        if (!isSupported()) {
+            return;
+        }
+
+        setDozeMode(true);
+        setAppIdle(true);
+
+        try {
+            assertBackgroundNetworkAccess(false);
+
+            // UID still shouldn't have access because of Doze.
+            addAppIdleWhitelist(mUid);
+            assertBackgroundNetworkAccess(false);
+
+            removeAppIdleWhitelist(mUid);
+            assertBackgroundNetworkAccess(false);
+        } finally {
+            setAppIdle(false);
+            setDozeMode(false);
+        }
+    }
+
+    public void testAppIdleAndDoze_tempPowerSaveAndAppIdleWhitelists() throws Exception {
+        if (!isSupported()) {
+            return;
+        }
+
+        setDozeMode(true);
+        setAppIdle(true);
+
+        try {
+            assertBackgroundNetworkAccess(false);
+
+            addAppIdleWhitelist(mUid);
+            assertBackgroundNetworkAccess(false);
+
+            addTempPowerSaveModeWhitelist(TEST_APP2_PKG, TEMP_POWERSAVE_WHITELIST_DURATION_MS);
+            assertBackgroundNetworkAccess(true);
+
+            // Wait until the whitelist duration is expired.
+            SystemClock.sleep(TEMP_POWERSAVE_WHITELIST_DURATION_MS);
+            assertBackgroundNetworkAccess(false);
+        } finally {
+            setAppIdle(false);
+            setDozeMode(false);
+            removeAppIdleWhitelist(mUid);
+        }
+    }
+
+    public void testAppIdleAndBatterySaver_tempPowerSaveAndAppIdleWhitelists() throws Exception {
+        if (!isSupported()) {
+            return;
+        }
+
+        setBatterySaverMode(true);
+        setAppIdle(true);
+
+        try {
+            assertBackgroundNetworkAccess(false);
+
+            addAppIdleWhitelist(mUid);
+            assertBackgroundNetworkAccess(false);
+
+            addTempPowerSaveModeWhitelist(TEST_APP2_PKG, TEMP_POWERSAVE_WHITELIST_DURATION_MS);
+            assertBackgroundNetworkAccess(true);
+
+            // Wait until the whitelist duration is expired.
+            SystemClock.sleep(TEMP_POWERSAVE_WHITELIST_DURATION_MS);
+            assertBackgroundNetworkAccess(false);
+        } finally {
+            setAppIdle(false);
+            setBatterySaverMode(false);
+            removeAppIdleWhitelist(mUid);
+        }
+    }
 }
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 fe9d36c..5f5ea43 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
@@ -156,6 +156,11 @@
                 "testBackgroundNetworkAccess_enabled");
     }
 
+    public void testAppIdleMetered_idleWhitelisted() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleMeteredTest",
+                "testAppIdleNetworkAccess_idleWhitelisted");
+    }
+
     // TODO: currently power-save mode and idle uses the same whitelist, so this test would be
     // redundant (as it would be testing the same as testBatterySaverMode_reinstall())
     //    public void testAppIdle_reinstall() throws Exception {
@@ -181,6 +186,11 @@
                 "testBackgroundNetworkAccess_enabled");
     }
 
+    public void testAppIdleNonMetered_idleWhitelisted() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest",
+                "testAppIdleNetworkAccess_idleWhitelisted");
+    }
+
     public void testAppIdleNonMetered_whenCharging() throws Exception {
         runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest",
                 "testAppIdleNetworkAccess_whenCharging");
@@ -281,6 +291,21 @@
                 "testAppIdleAndBatterySaver_tempPowerSaveWhitelists");
     }
 
+    public void testDozeAndAppIdle_appIdleWhitelist() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest",
+                "testDozeAndAppIdle_appIdleWhitelist");
+    }
+
+    public void testAppIdleAndDoze_tempPowerSaveAndAppIdleWhitelists() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest",
+                "testAppIdleAndDoze_tempPowerSaveAndAppIdleWhitelists");
+    }
+
+    public void testAppIdleAndBatterySaver_tempPowerSaveAndAppIdleWhitelists() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest",
+                "testAppIdleAndBatterySaver_tempPowerSaveAndAppIdleWhitelists");
+    }
+
     /*******************
      * Helper methods. *
      *******************/