Merge cherrypicks of ['android-review.googlesource.com/3132930'] into 24Q3-release.

Change-Id: I88390840922ba5c285f25e7d6066803b2b35d8ba
diff --git a/tests/src/android/cts/statsd/metadata/MetadataTests.java b/tests/src/android/cts/statsd/metadata/MetadataTests.java
index 56df8d6..fb35878 100644
--- a/tests/src/android/cts/statsd/metadata/MetadataTests.java
+++ b/tests/src/android/cts/statsd/metadata/MetadataTests.java
@@ -28,6 +28,7 @@
 import com.android.os.AtomsProto;
 import com.android.os.AtomsProto.Atom;
 import com.android.os.StatsLog.StatsdStatsReport;
+import com.android.os.StatsLog.StatsdStatsReport.AtomStats;
 import com.android.os.StatsLog.StatsdStatsReport.ConfigStats;
 import com.android.os.StatsLog.StatsdStatsReport.LogLossStats;
 import com.android.os.StatsLog.StatsdStatsReport.SocketLossStats.LossStatsPerUid;
@@ -237,6 +238,7 @@
 
         final String testPkgName = "com.android.statsd.app.atomstorm";
         final String testApk = "StatsdAtomStormApp.apk";
+        final int runAttemptsPerPackage = 10;
 
         String[][] testPkgs = {
             {testPkgName, ".StatsdAtomStorm", "testLogManyAtomsBackToBack"},
@@ -254,29 +256,57 @@
         StatsdStatsReport report = getStatsdStatsReport();
         assertThat(report).isNotNull();
 
-        // since the statsdstats accumulated from boot - we need to look only into diff if any
-        final HashSet<Integer> initialUids = getSocketLossUids(report);
-        HashSet<Integer> reportedUids = new HashSet<Integer>();
+        HashSet<Integer> reportedUids = getSocketLossUids(report);
 
         // intention is to run two distinct package tests to collect 2 different uids
         for (String[] pkg : testPkgs) {
-            DeviceUtils.runDeviceTests(getDevice(), pkg[0], pkg[1], pkg[2]);
+            report = runTestUntilLossAtomReported(pkg[0], pkg[1], pkg[2], runAttemptsPerPackage);
+            if (report == null) {
+                // the test run failed or the system throughput is sufficiently
+                // high to consume all event from stress test
+                DeviceUtils.uninstallTestApp(getDevice(), testPkgName);
+                return;
+            }
+            reportedUids.addAll(getSocketLossUids(report));
+        }
+
+        assertThat(reportedUids.size()).isGreaterThan(1);
+
+        DeviceUtils.uninstallTestApp(getDevice(), testPkgName);
+    }
+
+    private StatsdStatsReport runTestUntilLossAtomReported(
+            String pkg, String cls, String test, int maxIterationCount) throws Exception {
+        final int StatsSocketLossReportedAtomId = 752;
+
+        // idea is to run event store test app to simulate atom loss event and
+        // see if new StatsSocketLossReported instances are reported
+        StatsdStatsReport report = getStatsdStatsReport();
+        int socketLossAtomCount = getAtomStatsCount(report, StatsSocketLossReportedAtomId);
+        for (int attempt = 0; attempt < maxIterationCount; attempt++) {
+            DeviceUtils.runDeviceTests(getDevice(), pkg, cls, test);
 
             // the sleep is required since atoms are processed in async way by statsd
             // need to give time so statsd will process SocketLossStats atom
             RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_SHORT);
-            LogUtil.CLog.d(
-                    "testAtomIdLossDistributionCollection getStatsdStatsReport for " + pkg[0]);
+            LogUtil.CLog.d("runTestUntilLossAtomReported iteration " + attempt + " for " + pkg);
             report = getStatsdStatsReport();
-            assertThat(report).isNotNull();
-            reportedUids.addAll(getSocketLossUids(report));
+            int newCount = getAtomStatsCount(report, StatsSocketLossReportedAtomId);
+            if (socketLossAtomCount < newCount) {
+                return report;
+            }
         }
+        return null;
+    }
 
-        // obtaining the diff between initial loss info and loss info collected during the test
-        reportedUids.removeAll(initialUids);
-        assertThat(reportedUids.size()).isGreaterThan(1);
-
-        DeviceUtils.uninstallTestApp(getDevice(), testPkgName);
+    private int getAtomStatsCount(StatsdStatsReport report, int atomId) {
+        assertThat(report).isNotNull();
+        for (AtomStats atomStats : report.getAtomStatsList()) {
+            if (atomStats.getTag() == atomId) {
+                return atomStats.getCount();
+            }
+        }
+        return 0;
     }
 
     static private HashSet<Integer> getSocketLossUids(StatsdStatsReport report) {