Snap for 12210778 from 94120287d0875de9c0beeea4ead803879ff7c72c to 24Q4-release

Change-Id: I63f289a85c90796b7c019ab334c74c4b246cd3bb
diff --git a/common/FlaggedApi.bp b/common/FlaggedApi.bp
index 21be1d3..d5cfde3 100644
--- a/common/FlaggedApi.bp
+++ b/common/FlaggedApi.bp
@@ -22,6 +22,16 @@
     visibility: ["//packages/modules/Connectivity:__subpackages__"],
 }
 
+java_aconfig_library {
+    name: "com.android.net.flags-aconfig-java",
+    aconfig_declarations: "com.android.net.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+    min_sdk_version: "30",
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 aconfig_declarations {
     name: "com.android.net.thread.flags-aconfig",
     package: "com.android.net.thread.flags",
diff --git a/common/flags.aconfig b/common/flags.aconfig
index b320b61..1b0da4e 100644
--- a/common/flags.aconfig
+++ b/common/flags.aconfig
@@ -123,3 +123,11 @@
   description: "Flag for introducing TETHERING_VIRTUAL type"
   bug: "340376953"
 }
+
+flag {
+  name: "netstats_add_entries"
+  is_exported: true
+  namespace: "android_core_networking"
+  description: "Flag for NetworkStats#addEntries API"
+  bug: "335680025"
+}
diff --git a/framework-t/Android.bp b/framework-t/Android.bp
index f076f5b..ac78d09 100644
--- a/framework-t/Android.bp
+++ b/framework-t/Android.bp
@@ -137,6 +137,10 @@
     // framework-connectivity-pre-jarjar match at runtime.
     jarjar_rules: ":framework-connectivity-jarjar-rules",
     stub_only_libs: [
+        // static_libs is not used to compile stubs. So libs which have
+        // been included in static_libs might still need to
+        // be in stub_only_libs to be usable when generating the API stubs.
+        "com.android.net.flags-aconfig-java",
         // Use prebuilt framework-connectivity stubs to avoid circular dependencies
         "sdk_module-lib_current_framework-connectivity",
     ],
diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt
index 52de1a3..2354882 100644
--- a/framework-t/api/system-current.txt
+++ b/framework-t/api/system-current.txt
@@ -310,6 +310,7 @@
   public final class NetworkStats implements java.lang.Iterable<android.net.NetworkStats.Entry> android.os.Parcelable {
     ctor public NetworkStats(long, int);
     method @NonNull public android.net.NetworkStats add(@NonNull android.net.NetworkStats);
+    method @FlaggedApi("com.android.net.flags.netstats_add_entries") @NonNull public android.net.NetworkStats addEntries(@NonNull java.util.List<android.net.NetworkStats.Entry>);
     method @NonNull public android.net.NetworkStats addEntry(@NonNull android.net.NetworkStats.Entry);
     method public android.net.NetworkStats clone();
     method public int describeContents();
diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java
index e9a3f58..a2c4fc3 100644
--- a/framework-t/src/android/net/NetworkStats.java
+++ b/framework-t/src/android/net/NetworkStats.java
@@ -18,6 +18,7 @@
 
 import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -33,6 +34,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.modules.utils.build.SdkLevel;
+import com.android.net.flags.Flags;
 import com.android.net.module.util.CollectionUtils;
 
 import libcore.util.EmptyArray;
@@ -845,6 +847,21 @@
     }
 
     /**
+     * Adds multiple entries to a copy of this NetworkStats instance.
+     *
+     * @param entries The entries to add.
+     * @return A new NetworkStats instance with the added entries.
+     */
+    @FlaggedApi(Flags.FLAG_NETSTATS_ADD_ENTRIES)
+    public @NonNull NetworkStats addEntries(@NonNull final List<Entry> entries) {
+        final NetworkStats newStats = this.clone();
+        for (final Entry entry : Objects.requireNonNull(entries)) {
+            newStats.combineValues(entry);
+        }
+        return newStats;
+    }
+
+    /**
      * Add given values with an existing row, or create a new row if
      * {@link #findIndex(String, int, int, int, int, int, int)} is unable to find match. Can
      * also be used to subtract values from existing rows.
diff --git a/framework/Android.bp b/framework/Android.bp
index 282ba4b..deea6b6 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -86,6 +86,7 @@
         "framework-wifi.stubs.module_lib",
     ],
     static_libs: [
+        "com.android.net.flags-aconfig-java",
         // Not using the latest stable version because all functions in the latest version of
         // mdns_aidl_interface are deprecated.
         "mdns_aidl_interface-V1-java",
diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp
index c141b73..ed0670d 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -450,6 +450,7 @@
     visibility: ["//packages/modules/Connectivity/service-t"],
 }
 
+// net-utils-framework-connectivity is only for framework-connectivity.
 java_library {
     name: "net-utils-framework-connectivity",
     srcs: [
@@ -462,8 +463,7 @@
         "//apex_available:platform",
     ],
     visibility: [
-        "//packages/modules/Connectivity:__subpackages__",
-        "//packages/modules/NetworkStack:__subpackages__",
+        "//packages/modules/Connectivity/framework",
     ],
     libs: [
         "androidx.annotation_annotation",
@@ -502,10 +502,6 @@
         "com.android.tethering",
         "//apex_available:platform",
     ],
-    visibility: [
-        "//packages/modules/CaptivePortalLogin:__subpackages__",
-        "//packages/modules/Connectivity:__subpackages__",
-    ],
     defaults_visibility: [
         "//visibility:private",
     ],
@@ -515,6 +511,7 @@
     },
 }
 
+// net-utils-service-connectivity is only for service-connectivity.
 java_library {
     name: "net-utils-service-connectivity",
     srcs: [
@@ -528,6 +525,10 @@
     ],
     defaults: ["net-utils-non-bootclasspath-defaults"],
     jarjar_rules: "jarjar-rules-shared.txt",
+    visibility: [
+        "//packages/modules/Connectivity/service",
+        "//packages/modules/Connectivity/staticlibs/tests/unit",
+    ],
 }
 
 java_library {
@@ -538,6 +539,10 @@
     ],
     defaults: ["net-utils-non-bootclasspath-defaults"],
     jarjar_rules: "jarjar-rules-shared.txt",
+    visibility: [
+        "//packages/modules/CaptivePortalLogin:__subpackages__",
+        "//packages/modules/Connectivity/Tethering",
+    ],
 }
 
 aidl_interface {
diff --git a/staticlibs/testutils/Android.bp b/staticlibs/testutils/Android.bp
index 4749e75..8c71a91 100644
--- a/staticlibs/testutils/Android.bp
+++ b/staticlibs/testutils/Android.bp
@@ -42,7 +42,6 @@
         "net-utils-device-common-struct",
         "net-utils-device-common-struct-base",
         "net-utils-device-common-wear",
-        "net-utils-framework-connectivity",
         "modules-utils-build_system",
     ],
     lint: {
diff --git a/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt b/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt
index 8cef6aa..17f5e96 100644
--- a/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt
+++ b/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt
@@ -28,18 +28,26 @@
 import android.net.NetworkStats.SET_DEFAULT
 import android.net.NetworkStats.SET_FOREGROUND
 import android.net.NetworkStats.TAG_NONE
+import android.os.Build
 import androidx.test.filters.SmallTest
+import com.android.testutils.ConnectivityModuleTest
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
+import com.android.testutils.DevSdkIgnoreRunner
 import com.android.testutils.assertNetworkStatsEquals
 import com.android.testutils.assertParcelingIsLossless
 import kotlin.test.assertEquals
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
 
-@RunWith(JUnit4::class)
+@DevSdkIgnoreRunner.MonitorThreadLeak
+@RunWith(DevSdkIgnoreRunner::class)
 @SmallTest
 class NetworkStatsApiTest {
+    @get:Rule
+    val ignoreRule = DevSdkIgnoreRule()
     private val testStatsEmpty = NetworkStats(0L, 0)
 
     // Note that these variables need to be initialized outside of constructor, initialize
@@ -49,6 +57,7 @@
     // be merged if performing add on these 2 stats.
     private lateinit var testStats1: NetworkStats
     private lateinit var testStats2: NetworkStats
+    private lateinit var expectedEntriesInStats2: List<Entry>
 
     // This is a result of adding stats1 and stats2, while the merging of common key items is
     // subject to test later, this should not be initialized with for a loop to add stats1
@@ -84,19 +93,23 @@
                         METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 1, 6, 2, 0))
         assertEquals(8, testStats1.size())
 
-        testStats2 = NetworkStats(0L, 0)
-                // Entries which are common for set1 and set2.
-                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 15, 2, 31, 1))
-                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45))
-                .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 11, 2, 3, 4, 7))
-                .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4, 3, 2, 1, 0))
-                // Entry which only appears in set2.
-                .addEntry(Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0))
+        expectedEntriesInStats2 = listOf(
+            // Entries which are common for set1 and set2.
+            Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80,
+                  METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 15, 2, 31, 1),
+            Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE,
+                  METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45),
+            Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE,
+                  METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 11, 2, 3, 4, 7),
+            Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                  METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4, 3, 2, 1, 0),
+            // Entry which only appears in set2.
+            Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE,
+                  METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0))
+        testStats2 = NetworkStats(0L, 5)
+        for (entry in expectedEntriesInStats2) {
+            testStats2 = testStats2.addEntry(entry)
+        }
         assertEquals(5, testStats2.size())
 
         testStats3 = NetworkStats(0L, 9)
@@ -125,18 +138,6 @@
 
     @Test
     fun testAddEntry() {
-        val expectedEntriesInStats2 = arrayOf(
-                Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 15, 2, 31, 1),
-                Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45),
-                Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 11, 2, 3, 4, 7),
-                Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4, 3, 2, 1, 0),
-                Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0))
-
         // While testStats* are already initialized with addEntry, verify content added
         // matches expectation.
         for (i in expectedEntriesInStats2.indices) {
@@ -150,6 +151,27 @@
         assertEquals(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
                 METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 16, -2, 9, 1, 9),
                 stats.getValues(3, null))
+
+        // Verify the original ststs object is not altered.
+        for (i in expectedEntriesInStats2.indices) {
+            val entry = testStats2.getValues(i, null)
+            assertEquals(expectedEntriesInStats2[i], entry)
+        }
+    }
+
+    @ConnectivityModuleTest
+    @IgnoreUpTo(Build.VERSION_CODES.S_V2) // Mainlined NetworkStats only runs on T+
+    @Test
+    fun testAddEntries() {
+        val baseStats = NetworkStats(0L, 1)
+                .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 12, -5, 7, 0, 9))
+        val statsUnderTest = baseStats.addEntries(expectedEntriesInStats2)
+        // Assume the correctness of addEntry is verified in other tests.
+        val expectedStats = testStats2
+                .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 12, -5, 7, 0, 9))
+        assertNetworkStatsEquals(expectedStats, statsUnderTest)
     }
 
     @Test
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 9458460..88c2d5a 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -206,6 +206,7 @@
 import com.android.networkstack.apishim.common.ConnectivityManagerShim;
 import com.android.testutils.AutoReleaseNetworkCallbackRule;
 import com.android.testutils.CompatUtil;
+import com.android.testutils.ConnectUtil;
 import com.android.testutils.ConnectivityModuleTest;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
@@ -2942,20 +2943,10 @@
         // This may also apply to wifi in principle, but in practice methods that mock validation
         // URL all disconnect wifi forcefully anyway, so don't wait for wifi to validate.
         if (mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)) {
-            ensureValidatedNetwork(makeCellNetworkRequest());
+            new ConnectUtil(mContext).ensureCellularValidated();
         }
     }
 
-    private void ensureValidatedNetwork(NetworkRequest request) {
-        final TestableNetworkCallback cb = new TestableNetworkCallback();
-        mCm.registerNetworkCallback(request, cb);
-        cb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED,
-                NETWORK_CALLBACK_TIMEOUT_MS,
-                entry -> ((CallbackEntry.CapabilitiesChanged) entry).getCaps()
-                        .hasCapability(NET_CAPABILITY_VALIDATED));
-        mCm.unregisterNetworkCallback(cb);
-    }
-
     @AppModeFull(reason = "WRITE_DEVICE_CONFIG permission can't be granted to instant apps")
     @Test
     public void testAcceptPartialConnectivity_validatedNetwork() throws Exception {