add cts for unprivileged keepalive slots

Currently, unprivileged Nat-T keepalives are limited to 1 slot
per uid. Add CTS to verify that the keepalive slots are limited
as customized for unprivileged requests.

Bug: 129371366
Test: atest android.net.cts
      .ConnectivityManagerTest#testSocketKeepaliveUnprivileged
      --generate-new-metrics 10

Change-Id: I60b9e9ae9cf2b63490493ced9738cd2f402c3f9b
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index e89a422..ea441a7 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -1184,6 +1184,16 @@
         return s;
     }
 
+    private int getSupportedKeepalivesFromRes() throws Exception {
+        final Network network = ensureWifiConnected();
+        final NetworkCapabilities nc = mCm.getNetworkCapabilities(network);
+
+        // Get number of supported concurrent keepalives for testing network.
+        final int[] keepalivesPerTransport = KeepaliveUtils.getSupportedKeepalives(mContext);
+        return KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(
+                keepalivesPerTransport, nc);
+    }
+
     private boolean isKeepaliveSupported() throws Exception {
         final Network network = ensureWifiConnected();
         final Executor executor = mContext.getMainExecutor();
@@ -1293,7 +1303,8 @@
     }
 
     private int createConcurrentSocketKeepalives(int nattCount, int tcpCount) throws Exception {
-        if (!isKeepaliveSupported()) return 0;
+        // Use customization value in resource to prevent the need of privilege.
+        if (getSupportedKeepalivesFromRes() == 0) return 0;
 
         final Network network = ensureWifiConnected();
 
@@ -1374,16 +1385,10 @@
     public void testSocketKeepaliveLimit() throws Exception {
         adoptShellPermissionIdentity();
 
-        final Network network = ensureWifiConnected();
-        final NetworkCapabilities nc = mCm.getNetworkCapabilities(network);
+        final int supported = getSupportedKeepalivesFromRes();
 
-        // Get number of supported concurrent keepalives for testing network.
-        final int[] keepalivesPerTransport = KeepaliveUtils.getSupportedKeepalives(mContext);
-        final int supported = KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(
-                keepalivesPerTransport, nc);
-
-        // Sanity check.
         if (!isKeepaliveSupported()) {
+            // Sanity check.
             assertEquals(0, supported);
             return;
         }
@@ -1408,6 +1413,34 @@
         dropShellPermissionIdentity();
     }
 
+    /**
+     * Verifies that the keepalive slots are limited as customized for unprivileged requests.
+     */
+    public void testSocketKeepaliveUnprivileged() throws Exception {
+        final int supported = getSupportedKeepalivesFromRes();
+
+        adoptShellPermissionIdentity();
+        if (!isKeepaliveSupported()) {
+            // Sanity check.
+            assertEquals(0, supported);
+            return;
+        }
+        dropShellPermissionIdentity();
+
+        final int allowedUnprivilegedPerUid = mContext.getResources().getInteger(
+                R.integer.config_allowedUnprivilegedKeepalivePerUid);
+        final int reservedPrivilegedSlots = mContext.getResources().getInteger(
+                R.integer.config_reservedPrivilegedKeepaliveSlots);
+        // Verifies that unprivileged request per uid cannot exceed the limit customized in the
+        // resource. Currently, unprivileged keepalive slots are limited to Nat-T only, this test
+        // does not apply to TCP.
+        assertGreaterOrEqual(supported, reservedPrivilegedSlots);
+        assertGreaterOrEqual(supported, allowedUnprivilegedPerUid);
+        final int expectedUnprivileged =
+                Math.min(allowedUnprivilegedPerUid, supported - reservedPrivilegedSlots);
+        assertEquals(expectedUnprivileged, createConcurrentSocketKeepalives(supported + 1, 0));
+    }
+
     private static void assertGreaterOrEqual(long greater, long lesser) {
         assertTrue("" + greater + " expected to be greater than or equal to " + lesser,
                 greater >= lesser);