Snap for 8581162 from 19a244c33ec1990f81a430f28bb9b9b0c6932ca0 to tm-release

Change-Id: Ic5d3715539651b810e7ff69c3340b45789d5240b
diff --git a/apex/apex_manifest.json b/apex/apex_manifest.json
index 8578182..84f2397 100644
--- a/apex/apex_manifest.json
+++ b/apex/apex_manifest.json
@@ -1,5 +1,5 @@
 {
   "name": "com.android.os.statsd",
-  "version": 330000000
+  "version": 330090000
 }
 
diff --git a/statsd/tests/e2e/CountMetric_e2e_test.cpp b/statsd/tests/e2e/CountMetric_e2e_test.cpp
index f92516b..ef183b7 100644
--- a/statsd/tests/e2e/CountMetric_e2e_test.cpp
+++ b/statsd/tests/e2e/CountMetric_e2e_test.cpp
@@ -1617,6 +1617,136 @@
               TestAtomReported::OFF);
 }
 
+TEST(CountMetricE2eTest, TestConditionSlicedByRepeatedUidWithUidDimension) {
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    AtomMatcher uidProcessStateChangedAtomMatcher = CreateUidProcessStateChangedAtomMatcher();
+    AtomMatcher repeatedStateFirstOffAtomMatcher = CreateTestAtomRepeatedStateFirstOffAtomMatcher();
+    AtomMatcher repeatedStateFirstOnAtomMatcher = CreateTestAtomRepeatedStateFirstOnAtomMatcher();
+    *config.add_atom_matcher() = uidProcessStateChangedAtomMatcher;
+    *config.add_atom_matcher() = repeatedStateFirstOffAtomMatcher;
+    *config.add_atom_matcher() = repeatedStateFirstOnAtomMatcher;
+
+    Predicate testAtomRepeatedStateFirstOffPerUidPredicate =
+            CreateTestAtomRepeatedStateFirstOffPredicate();
+    FieldMatcher* dimensions =
+            testAtomRepeatedStateFirstOffPerUidPredicate.mutable_simple_predicate()
+                    ->mutable_dimensions();
+    *dimensions = CreateRepeatedDimensions(util::TEST_ATOM_REPORTED, {9 /* repeated uid*/},
+                                           {Position::FIRST});
+    *config.add_predicate() = testAtomRepeatedStateFirstOffPerUidPredicate;
+
+    int64_t metricId = 123456;
+    CountMetric* countMetric = config.add_count_metric();
+    countMetric->set_id(metricId);
+    countMetric->set_what(uidProcessStateChangedAtomMatcher.id());
+    countMetric->set_condition(testAtomRepeatedStateFirstOffPerUidPredicate.id());
+    countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+    *countMetric->mutable_dimensions_in_what() =
+            CreateDimensions(util::UID_PROCESS_STATE_CHANGED, {1 /*uid*/});
+    MetricConditionLink* links = countMetric->add_links();
+    links->set_condition(testAtomRepeatedStateFirstOffPerUidPredicate.id());
+    *links->mutable_fields_in_what() =
+            CreateDimensions(util::UID_PROCESS_STATE_CHANGED, {1 /* uid*/});
+    *links->mutable_fields_in_condition() = CreateRepeatedDimensions(
+            util::TEST_ATOM_REPORTED, {9 /* repeated uid*/}, {Position::FIRST});
+
+    // Initialize StatsLogProcessor.
+    ConfigKey cfgKey(2000, 921);
+    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+    const uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+    const uint64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
+    sp<StatsLogProcessor> processor =
+            CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+    vector<int> intArray1 = {1, 2};
+    vector<int> intArray2 = {2, 1};
+    vector<int> enumArrayOn = {TestAtomReported::ON, TestAtomReported::OFF};
+    vector<int> enumArrayOff = {TestAtomReported::OFF, TestAtomReported::ON};
+
+    std::vector<std::unique_ptr<LogEvent>> events;
+    // Set condition to true for uid 1.
+    events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
+            bucketStartTimeNs + 20 * NS_PER_SEC, intArray1, {}, {}, {}, {}, 0, enumArrayOff));
+
+    // Uid 1 process state changed.
+    events.push_back(CreateUidProcessStateChangedEvent(
+            bucketStartTimeNs + 40 * NS_PER_SEC, 1 /*uid*/,
+            android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
+    // Uid 2 process state changed. Should not be counted.
+    events.push_back(CreateUidProcessStateChangedEvent(
+            bucketStartTimeNs + 60 * NS_PER_SEC, 2 /*uid*/,
+            android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
+
+    // Set condition to true for uid 2.
+    events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
+            bucketStartTimeNs + 80 * NS_PER_SEC, intArray2, {}, {}, {}, {}, 0, enumArrayOff));
+    // Uid 1 process state changed.
+    events.push_back(CreateUidProcessStateChangedEvent(
+            bucketStartTimeNs + 100 * NS_PER_SEC, 1 /*uid*/,
+            android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
+    // Uid 2 process state changed.
+    events.push_back(CreateUidProcessStateChangedEvent(
+            bucketStartTimeNs + 120 * NS_PER_SEC, 2 /*uid*/,
+            android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
+
+    // Bucket 2
+    // Set condition to false for uid 1.
+    events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
+            bucket2StartTimeNs + 20 * NS_PER_SEC, intArray1, {}, {}, {}, {}, 0, enumArrayOn));
+    // Uid 1 process state changed. Should not be counted.
+    events.push_back(CreateUidProcessStateChangedEvent(
+            bucket2StartTimeNs + 40 * NS_PER_SEC, 1 /*uid*/,
+            android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
+    // Uid 2 process state changed.
+    events.push_back(CreateUidProcessStateChangedEvent(
+            bucket2StartTimeNs + 60 * NS_PER_SEC, 2 /*uid*/,
+            android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
+
+    // Send log events to StatsLogProcessor.
+    for (auto& event : events) {
+        processor->OnLogEvent(event.get());
+    }
+
+    // Check dump report.
+    vector<uint8_t> buffer;
+    ConfigMetricsReportList reports;
+    processor->onDumpReport(cfgKey, bucket2StartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
+                            FAST, &buffer);
+    ASSERT_GT(buffer.size(), 0);
+    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+    backfillDimensionPath(&reports);
+    backfillStringInReport(&reports);
+    backfillStartEndTimestamp(&reports);
+
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
+    EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
+    StatsLogReport::CountMetricDataWrapper countMetrics;
+    sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+    ASSERT_EQ(2, countMetrics.data_size());
+
+    CountMetricData data = countMetrics.data(0);
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+    ASSERT_EQ(1, data.bucket_info_size());
+    ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
+                        2);
+
+    data = countMetrics.data(1);
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+    EXPECT_EQ(2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+    ASSERT_EQ(2, data.bucket_info_size());
+    ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
+                        1);
+    ValidateCountBucket(data.bucket_info(1), bucket2StartTimeNs, bucket2StartTimeNs + bucketSizeNs,
+                        1);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android