1 /*
2  * Copyright (C) 2019, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gtest/gtest.h>
18 
19 #include "src/StatsLogProcessor.h"
20 #include "src/state/StateManager.h"
21 #include "src/state/StateTracker.h"
22 #include "tests/statsd_test_util.h"
23 
24 namespace android {
25 namespace os {
26 namespace statsd {
27 
28 #ifdef __ANDROID__
29 
30 /**
31  * Tests the initial condition and condition after the first log events for
32  * count metrics with either a combination condition or simple condition.
33  *
34  * Metrics should be initialized with condition kUnknown (given that the
35  * predicate is using the default InitialValue of UNKNOWN). The condition should
36  * be updated to either kFalse or kTrue if a condition event is logged for all
37  * children conditions.
38  */
TEST(CountMetricE2eTest,TestInitialConditionChanges)39 TEST(CountMetricE2eTest, TestInitialConditionChanges) {
40     // Initialize config.
41     StatsdConfig config;
42     config.add_default_pull_packages("AID_ROOT");  // Fake puller is registered with root.
43 
44     auto syncStartMatcher = CreateSyncStartAtomMatcher();
45     *config.add_atom_matcher() = syncStartMatcher;
46     *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
47     *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
48     *config.add_atom_matcher() = CreateBatteryStateNoneMatcher();
49     *config.add_atom_matcher() = CreateBatteryStateUsbMatcher();
50 
51     auto screenOnPredicate = CreateScreenIsOnPredicate();
52     *config.add_predicate() = screenOnPredicate;
53 
54     auto deviceUnpluggedPredicate = CreateDeviceUnpluggedPredicate();
55     *config.add_predicate() = deviceUnpluggedPredicate;
56 
57     auto screenOnOnBatteryPredicate = config.add_predicate();
58     screenOnOnBatteryPredicate->set_id(StringToId("screenOnOnBatteryPredicate"));
59     screenOnOnBatteryPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
60     addPredicateToPredicateCombination(screenOnPredicate, screenOnOnBatteryPredicate);
61     addPredicateToPredicateCombination(deviceUnpluggedPredicate, screenOnOnBatteryPredicate);
62 
63     // CountSyncStartWhileScreenOnOnBattery (CombinationCondition)
64     CountMetric* countMetric1 = config.add_count_metric();
65     countMetric1->set_id(StringToId("CountSyncStartWhileScreenOnOnBattery"));
66     countMetric1->set_what(syncStartMatcher.id());
67     countMetric1->set_condition(screenOnOnBatteryPredicate->id());
68     countMetric1->set_bucket(FIVE_MINUTES);
69 
70     // CountSyncStartWhileOnBattery (SimpleCondition)
71     CountMetric* countMetric2 = config.add_count_metric();
72     countMetric2->set_id(StringToId("CountSyncStartWhileOnBatterySliceScreen"));
73     countMetric2->set_what(syncStartMatcher.id());
74     countMetric2->set_condition(deviceUnpluggedPredicate.id());
75     countMetric2->set_bucket(FIVE_MINUTES);
76 
77     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
78     const uint64_t bucketSizeNs =
79             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
80     int uid = 12345;
81     int64_t cfgId = 98765;
82     ConfigKey cfgKey(uid, cfgId);
83     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
84 
85     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
86     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
87     EXPECT_TRUE(metricsManager->isConfigValid());
88     EXPECT_EQ(2, metricsManager->mAllMetricProducers.size());
89 
90     sp<MetricProducer> metricProducer1 = metricsManager->mAllMetricProducers[0];
91     sp<MetricProducer> metricProducer2 = metricsManager->mAllMetricProducers[1];
92 
93     EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition);
94     EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition);
95 
96     auto screenOnEvent =
97             CreateScreenStateChangedEvent(bucketStartTimeNs + 30, android::view::DISPLAY_STATE_ON);
98     processor->OnLogEvent(screenOnEvent.get());
99     EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition);
100     EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition);
101 
102     auto pluggedUsbEvent = CreateBatteryStateChangedEvent(
103             bucketStartTimeNs + 50, BatteryPluggedStateEnum::BATTERY_PLUGGED_USB);
104     processor->OnLogEvent(pluggedUsbEvent.get());
105     EXPECT_EQ(ConditionState::kFalse, metricProducer1->mCondition);
106     EXPECT_EQ(ConditionState::kFalse, metricProducer2->mCondition);
107 
108     auto pluggedNoneEvent = CreateBatteryStateChangedEvent(
109             bucketStartTimeNs + 70, BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE);
110     processor->OnLogEvent(pluggedNoneEvent.get());
111     EXPECT_EQ(ConditionState::kTrue, metricProducer1->mCondition);
112     EXPECT_EQ(ConditionState::kTrue, metricProducer2->mCondition);
113 }
114 
TEST(CountMetricE2eTest,TestConditionTrueNanos)115 TEST(CountMetricE2eTest, TestConditionTrueNanos) {
116     // Initialize config.
117     StatsdConfig config;
118     config.add_default_pull_packages("AID_ROOT");  // Fake puller is registered with root.
119 
120     AtomMatcher syncStartMatcher = CreateSyncStartAtomMatcher();
121     *config.add_atom_matcher() = syncStartMatcher;
122     *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
123     *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
124 
125     AtomMatcher crashMatcher = CreateProcessCrashAtomMatcher();
126     *config.add_atom_matcher() = crashMatcher;
127 
128     Predicate screenOnPredicate = CreateScreenIsOnPredicate();
129     *config.add_predicate() = screenOnPredicate;
130 
131     CountMetric* countMetric = config.add_count_metric();
132     int64_t metricId = StringToId("CountSyncStartWhileScreenOn");
133     countMetric->set_id(metricId);
134     countMetric->set_what(syncStartMatcher.id());
135     countMetric->set_condition(screenOnPredicate.id());
136     countMetric->set_bucket(FIVE_MINUTES);
137 
138     MetricActivation* metricActivation = config.add_metric_activation();
139     metricActivation->set_metric_id(metricId);
140     EventActivation* eventActivation = metricActivation->add_event_activation();
141     eventActivation->set_atom_matcher_id(crashMatcher.id());
142     eventActivation->set_ttl_seconds(360);  // 6 minutes.
143 
144     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
145     const uint64_t bucketSizeNs =
146             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
147     const uint64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
148     const uint64_t bucket3StartTimeNs = bucket2StartTimeNs + bucketSizeNs;
149 
150     int uid = 12345;
151     int64_t cfgId = 98765;
152     ConfigKey cfgKey(uid, cfgId);
153     sp<StatsLogProcessor> processor =
154             CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
155 
156     std::vector<int> attributionUids1 = {123};
157     std::vector<string> attributionTags1 = {"App1"};
158     int64_t conditionStart1Ns = bucketStartTimeNs + 50 * NS_PER_SEC;
159     int64_t activationStart1Ns = bucketStartTimeNs + 70 * NS_PER_SEC;
160     int64_t conditionEnd1Ns = bucket2StartTimeNs + 35 * NS_PER_SEC;
161     int64_t conditionStart2Ns = bucket2StartTimeNs + 90 * NS_PER_SEC;
162     int64_t activationEnd1Ns = bucket2StartTimeNs + 140 * NS_PER_SEC;
163     int64_t conditionEnd2Ns = bucket2StartTimeNs + 155 * NS_PER_SEC;
164     int64_t activationStart2Ns = bucket2StartTimeNs + 200 * NS_PER_SEC;
165     int64_t conditionStart3Ns = bucket2StartTimeNs + 240 * NS_PER_SEC;
166     int64_t conditionEnd3Ns = bucket3StartTimeNs + 40 * NS_PER_SEC;
167     int64_t activationEnd2Ns = bucket3StartTimeNs + 270 * NS_PER_SEC;
168 
169     std::vector<std::unique_ptr<LogEvent>> events;
170     // Active false, condition becomes true.
171     events.push_back(CreateScreenStateChangedEvent(
172             conditionStart1Ns,
173             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 1:00
174     // Event not counted.
175     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 60 * NS_PER_SEC, attributionUids1,
176                                           attributionTags1, "sync_name"));  // 1:10
177     // Active becomes true, condition true.
178     events.push_back(CreateAppCrashEvent(activationStart1Ns, 111));  // 1:20
179     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 75 * NS_PER_SEC, attributionUids1,
180                                           attributionTags1, "sync_name"));  // 1:25
181 
182     // Bucket 2 starts. 5:10
183     events.push_back(CreateSyncStartEvent(bucket2StartTimeNs + 20 * NS_PER_SEC, attributionUids1,
184                                           attributionTags1, "sync_name"));  // 5:30
185     // Active true, condition becomes false.
186     events.push_back(CreateScreenStateChangedEvent(
187             conditionEnd1Ns,
188             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 5:45
189     // Event not counted.
190     events.push_back(CreateSyncStartEvent(bucket2StartTimeNs + 50 * NS_PER_SEC, attributionUids1,
191                                           attributionTags1, "sync_name"));  // 6:00
192     // Active true, condition becomes true.
193     events.push_back(CreateScreenStateChangedEvent(
194             conditionStart2Ns,
195             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 6:40
196     events.push_back(CreateSyncStartEvent(bucket2StartTimeNs + 110 * NS_PER_SEC, attributionUids1,
197                                           attributionTags1, "sync_name"));  // 7:00
198     // Active becomes false, condition true (activation expires).
199     // Event not counted.
200     events.push_back(CreateSyncStartEvent(activationEnd1Ns, attributionUids1, attributionTags1,
201                                           "sync_name"));  // 7:30
202     // Active false, condition becomes false.
203     events.push_back(CreateScreenStateChangedEvent(
204             conditionEnd2Ns,
205             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 7:45
206     // Event not counted.
207     events.push_back(CreateSyncStartEvent(bucket2StartTimeNs + 160 * NS_PER_SEC, attributionUids1,
208                                           attributionTags1, "sync_name"));  // 7:50
209     // Active becomes true, condition false.
210     events.push_back(CreateAppCrashEvent(activationStart2Ns, 111));  // 8:30
211     // Event not counted.
212     events.push_back(CreateSyncStartEvent(bucket2StartTimeNs + 220 * NS_PER_SEC, attributionUids1,
213                                           attributionTags1, "sync_name"));  // 8:50
214     // Active true, condition becomes true.
215     events.push_back(CreateScreenStateChangedEvent(
216             conditionStart3Ns,
217             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 9:10
218     events.push_back(CreateSyncStartEvent(bucket2StartTimeNs + 250 * NS_PER_SEC, attributionUids1,
219                                           attributionTags1, "sync_name"));  // 9:20
220 
221     // Bucket 3 starts. 10:10
222     events.push_back(CreateSyncStartEvent(bucket3StartTimeNs + 10 * NS_PER_SEC, attributionUids1,
223                                           attributionTags1, "sync_name"));  // 10:20
224     // Active true, condition becomes false.
225     events.push_back(CreateScreenStateChangedEvent(
226             conditionEnd3Ns,
227             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 10:50
228                                                                    // Event not counted.
229     events.push_back(CreateSyncStartEvent(bucket3StartTimeNs + 70 * NS_PER_SEC, attributionUids1,
230                                           attributionTags1, "sync_name"));  // 11:20
231     // Active becomes false, condition false (activation expires).
232     // Event not counted.
233     events.push_back(CreateSyncStartEvent(activationEnd2Ns, attributionUids1, attributionTags1,
234                                           "sync_name"));  // 14:40
235 
236     // Send log events to StatsLogProcessor.
237     for (auto& event : events) {
238         processor->OnLogEvent(event.get());
239     }
240 
241     // Check dump report.
242     vector<uint8_t> buffer;
243     ConfigMetricsReportList reports;
244     int64_t dumpReportTimeNs = bucket3StartTimeNs + 290 * NS_PER_SEC;  // 15:00
245     processor->onDumpReport(cfgKey, dumpReportTimeNs, true, true, ADB_DUMP, FAST, &buffer);
246     ASSERT_GT(buffer.size(), 0);
247     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
248     backfillDimensionPath(&reports);
249     backfillStringInReport(&reports);
250     backfillStartEndTimestamp(&reports);
251 
252     ASSERT_EQ(1, reports.reports_size());
253     ASSERT_EQ(1, reports.reports(0).metrics_size());
254     EXPECT_TRUE(reports.reports(0).metrics(0).has_estimated_data_bytes());
255     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
256     StatsLogReport::CountMetricDataWrapper countMetrics;
257     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
258     ASSERT_EQ(1, countMetrics.data_size());
259 
260     CountMetricData data = countMetrics.data(0);
261     ASSERT_EQ(4, data.bucket_info_size());
262     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucket2StartTimeNs, 1,
263                         bucket2StartTimeNs - activationStart1Ns);
264     ValidateCountBucket(
265             data.bucket_info(1), bucket2StartTimeNs, activationEnd1Ns, 2,
266             (conditionEnd1Ns - bucket2StartTimeNs) + (activationEnd1Ns - conditionStart2Ns));
267     ValidateCountBucket(data.bucket_info(2), activationEnd1Ns, bucket3StartTimeNs, 1,
268                         bucket3StartTimeNs - conditionStart3Ns);
269     ValidateCountBucket(data.bucket_info(3), bucket3StartTimeNs, activationEnd2Ns, 1,
270                         conditionEnd3Ns - bucket3StartTimeNs);
271 }
272 
273 /**
274 * Test a count metric that has one slice_by_state with no primary fields.
275 *
276 * Once the CountMetricProducer is initialized, it has one atom id in
277 * mSlicedStateAtoms and no entries in mStateGroupMap.
278 
279 * One StateTracker tracks the state atom, and it has one listener which is the
280 * CountMetricProducer that was initialized.
281 */
TEST(CountMetricE2eTest,TestSlicedState)282 TEST(CountMetricE2eTest, TestSlicedState) {
283     // Initialize config.
284     StatsdConfig config;
285 
286     auto syncStartMatcher = CreateSyncStartAtomMatcher();
287     *config.add_atom_matcher() = syncStartMatcher;
288 
289     auto state = CreateScreenState();
290     *config.add_state() = state;
291 
292     // Create count metric that slices by screen state.
293     int64_t metricId = 123456;
294     auto countMetric = config.add_count_metric();
295     countMetric->set_id(metricId);
296     countMetric->set_what(syncStartMatcher.id());
297     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
298     countMetric->add_slice_by_state(state.id());
299 
300     // Initialize StatsLogProcessor.
301     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
302     const uint64_t bucketSizeNs =
303             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
304     int uid = 12345;
305     int64_t cfgId = 98765;
306     ConfigKey cfgKey(uid, cfgId);
307     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
308 
309     // Check that CountMetricProducer was initialized correctly.
310     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
311     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
312     EXPECT_TRUE(metricsManager->isConfigValid());
313     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
314     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
315     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
316     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
317     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
318 
319     // Check that StateTrackers were initialized correctly.
320     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
321     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
322 
323     /*
324                bucket #1                      bucket #2
325     |     1     2     3     4     5     6     7     8     9     10 (minutes)
326     |-----------------------------|-----------------------------|--
327             x                x         x    x        x      x       (syncStartEvents)
328           |                                       |                 (ScreenIsOnEvent)
329                    |     |                                          (ScreenIsOffEvent)
330                                                         |           (ScreenDozeEvent)
331     */
332     // Initialize log events - first bucket.
333     std::vector<int> attributionUids1 = {123};
334     std::vector<string> attributionTags1 = {"App1"};
335 
336     std::vector<std::unique_ptr<LogEvent>> events;
337     events.push_back(CreateScreenStateChangedEvent(
338             bucketStartTimeNs + 50 * NS_PER_SEC,
339             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 1:00
340     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 75 * NS_PER_SEC, attributionUids1,
341                                           attributionTags1, "sync_name"));  // 1:25
342     events.push_back(CreateScreenStateChangedEvent(
343             bucketStartTimeNs + 150 * NS_PER_SEC,
344             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 2:40
345     events.push_back(CreateScreenStateChangedEvent(
346             bucketStartTimeNs + 200 * NS_PER_SEC,
347             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 3:30
348     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 250 * NS_PER_SEC, attributionUids1,
349                                           attributionTags1, "sync_name"));  // 4:20
350 
351     // Initialize log events - second bucket.
352     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 350 * NS_PER_SEC, attributionUids1,
353                                           attributionTags1, "sync_name"));  // 6:00
354     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 400 * NS_PER_SEC, attributionUids1,
355                                           attributionTags1, "sync_name"));  // 6:50
356     events.push_back(CreateScreenStateChangedEvent(
357             bucketStartTimeNs + 450 * NS_PER_SEC,
358             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 7:40
359     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 475 * NS_PER_SEC, attributionUids1,
360                                           attributionTags1, "sync_name"));  // 8:05
361     events.push_back(CreateScreenStateChangedEvent(
362             bucketStartTimeNs + 500 * NS_PER_SEC,
363             android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN));  // 8:30
364     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 520 * NS_PER_SEC, attributionUids1,
365                                           attributionTags1, "sync_name"));  // 8:50
366 
367     // Send log events to StatsLogProcessor.
368     for (auto& event : events) {
369         processor->OnLogEvent(event.get());
370     }
371 
372     // Check dump report.
373     vector<uint8_t> buffer;
374     ConfigMetricsReportList reports;
375     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
376                             FAST, &buffer);
377     ASSERT_GT(buffer.size(), 0);
378     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
379     backfillDimensionPath(&reports);
380     backfillStringInReport(&reports);
381     backfillStartEndTimestamp(&reports);
382 
383     ASSERT_EQ(1, reports.reports_size());
384     ASSERT_EQ(1, reports.reports(0).metrics_size());
385     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
386     StatsLogReport::CountMetricDataWrapper countMetrics;
387     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
388     ASSERT_EQ(3, countMetrics.data_size());
389 
390     // For each CountMetricData, check StateValue info is correct and buckets
391     // have correct counts.
392     auto data = countMetrics.data(0);
393     ASSERT_EQ(1, data.slice_by_state_size());
394     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
395     EXPECT_TRUE(data.slice_by_state(0).has_value());
396     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
397               data.slice_by_state(0).value());
398     ASSERT_EQ(1, data.bucket_info_size());
399     EXPECT_EQ(1, data.bucket_info(0).count());
400 
401     data = countMetrics.data(1);
402     ASSERT_EQ(1, data.slice_by_state_size());
403     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
404     EXPECT_TRUE(data.slice_by_state(0).has_value());
405     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
406     ASSERT_EQ(2, data.bucket_info_size());
407     EXPECT_EQ(1, data.bucket_info(0).count());
408     EXPECT_EQ(2, data.bucket_info(1).count());
409 
410     data = countMetrics.data(2);
411     ASSERT_EQ(1, data.slice_by_state_size());
412     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
413     EXPECT_TRUE(data.slice_by_state(0).has_value());
414     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
415     ASSERT_EQ(2, data.bucket_info_size());
416     EXPECT_EQ(1, data.bucket_info(0).count());
417     EXPECT_EQ(1, data.bucket_info(1).count());
418 }
419 
420 /**
421  * Test a count metric that has one slice_by_state with a mapping and no
422  * primary fields.
423  *
424  * Once the CountMetricProducer is initialized, it has one atom id in
425  * mSlicedStateAtoms and has one entry per state value in mStateGroupMap.
426  *
427  * One StateTracker tracks the state atom, and it has one listener which is the
428  * CountMetricProducer that was initialized.
429  */
TEST(CountMetricE2eTest,TestSlicedStateWithMap)430 TEST(CountMetricE2eTest, TestSlicedStateWithMap) {
431     // Initialize config.
432     StatsdConfig config;
433 
434     auto syncStartMatcher = CreateSyncStartAtomMatcher();
435     *config.add_atom_matcher() = syncStartMatcher;
436 
437     int64_t screenOnId = 4444;
438     int64_t screenOffId = 9876;
439     auto state = CreateScreenStateWithOnOffMap(screenOnId, screenOffId);
440     *config.add_state() = state;
441 
442     // Create count metric that slices by screen state with on/off map.
443     int64_t metricId = 123456;
444     auto countMetric = config.add_count_metric();
445     countMetric->set_id(metricId);
446     countMetric->set_what(syncStartMatcher.id());
447     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
448     countMetric->add_slice_by_state(state.id());
449 
450     // Initialize StatsLogProcessor.
451     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
452     const uint64_t bucketSizeNs =
453             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
454     int uid = 12345;
455     int64_t cfgId = 98765;
456     ConfigKey cfgKey(uid, cfgId);
457     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
458 
459     // Check that StateTrackers were initialized correctly.
460     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
461     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
462 
463     // Check that CountMetricProducer was initialized correctly.
464     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
465     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
466     EXPECT_TRUE(metricsManager->isConfigValid());
467     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
468     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
469     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
470     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
471     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 1);
472 
473     StateMap map = state.map();
474     for (auto group : map.group()) {
475         for (auto value : group.value()) {
476             EXPECT_EQ(metricProducer->mStateGroupMap.at(SCREEN_STATE_ATOM_ID).at(value),
477                       group.group_id());
478         }
479     }
480 
481     /*
482                bucket #1                      bucket #2
483     |     1     2     3     4     5     6     7     8     9     10 (minutes)
484     |-----------------------------|-----------------------------|--
485       x   x     x       x    x   x      x         x         x       (syncStartEvents)
486      -----------------------------------------------------------SCREEN_OFF events
487              |                  |                                   (ScreenStateOffEvent = 1)
488        |                  |                                         (ScreenStateDozeEvent = 3)
489                                                 |                   (ScreenStateDozeSuspendEvent =
490     4)
491      -----------------------------------------------------------SCREEN_ON events
492                    |                                       |        (ScreenStateOnEvent = 2)
493                       |                                             (ScreenStateVrEvent = 5)
494                                             |                       (ScreenStateOnSuspendEvent = 6)
495     */
496     // Initialize log events - first bucket.
497     std::vector<int> attributionUids1 = {123};
498     std::vector<string> attributionTags1 = {"App1"};
499 
500     std::vector<std::unique_ptr<LogEvent>> events;
501     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 20 * NS_PER_SEC, attributionUids1,
502                                           attributionTags1, "sync_name"));  // 0:30
503     events.push_back(CreateScreenStateChangedEvent(
504             bucketStartTimeNs + 30 * NS_PER_SEC,
505             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 0:40
506     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 60 * NS_PER_SEC, attributionUids1,
507                                           attributionTags1, "sync_name"));  // 1:10
508     events.push_back(CreateScreenStateChangedEvent(
509             bucketStartTimeNs + 90 * NS_PER_SEC,
510             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 1:40
511     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 120 * NS_PER_SEC, attributionUids1,
512                                           attributionTags1, "sync_name"));  // 2:10
513     events.push_back(CreateScreenStateChangedEvent(
514             bucketStartTimeNs + 150 * NS_PER_SEC,
515             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 2:40
516     events.push_back(CreateScreenStateChangedEvent(
517             bucketStartTimeNs + 180 * NS_PER_SEC,
518             android::view::DisplayStateEnum::DISPLAY_STATE_VR));  // 3:10
519     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 200 * NS_PER_SEC, attributionUids1,
520                                           attributionTags1, "sync_name"));  // 3:30
521     events.push_back(CreateScreenStateChangedEvent(
522             bucketStartTimeNs + 210 * NS_PER_SEC,
523             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 3:40
524     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 250 * NS_PER_SEC, attributionUids1,
525                                           attributionTags1, "sync_name"));  // 4:20
526     events.push_back(CreateScreenStateChangedEvent(
527             bucketStartTimeNs + 280 * NS_PER_SEC,
528             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 4:50
529     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 285 * NS_PER_SEC, attributionUids1,
530                                           attributionTags1, "sync_name"));  // 4:55
531 
532     // Initialize log events - second bucket.
533     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 360 * NS_PER_SEC, attributionUids1,
534                                           attributionTags1, "sync_name"));  // 6:10
535     events.push_back(CreateScreenStateChangedEvent(
536             bucketStartTimeNs + 390 * NS_PER_SEC,
537             android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND));  // 6:40
538     events.push_back(CreateScreenStateChangedEvent(
539             bucketStartTimeNs + 430 * NS_PER_SEC,
540             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE_SUSPEND));  // 7:20
541     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 440 * NS_PER_SEC, attributionUids1,
542                                           attributionTags1, "sync_name"));  // 7:30
543     events.push_back(CreateScreenStateChangedEvent(
544             bucketStartTimeNs + 540 * NS_PER_SEC,
545             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 9:10
546     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 570 * NS_PER_SEC, attributionUids1,
547                                           attributionTags1, "sync_name"));  // 9:40
548 
549     // Send log events to StatsLogProcessor.
550     for (auto& event : events) {
551         processor->OnLogEvent(event.get());
552     }
553 
554     // Check dump report.
555     vector<uint8_t> buffer;
556     ConfigMetricsReportList reports;
557     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
558                             FAST, &buffer);
559     ASSERT_GT(buffer.size(), 0);
560     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
561     backfillDimensionPath(&reports);
562     backfillStringInReport(&reports);
563     backfillStartEndTimestamp(&reports);
564 
565     ASSERT_EQ(1, reports.reports_size());
566     ASSERT_EQ(1, reports.reports(0).metrics_size());
567     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
568     StatsLogReport::CountMetricDataWrapper countMetrics;
569     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
570     ASSERT_EQ(3, countMetrics.data_size());
571 
572     // For each CountMetricData, check StateValue info is correct and buckets
573     // have correct counts.
574     auto data = countMetrics.data(0);
575     ASSERT_EQ(1, data.slice_by_state_size());
576     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
577     EXPECT_TRUE(data.slice_by_state(0).has_value());
578     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
579     ASSERT_EQ(1, data.bucket_info_size());
580     EXPECT_EQ(1, data.bucket_info(0).count());
581 
582     data = countMetrics.data(1);
583     ASSERT_EQ(1, data.slice_by_state_size());
584     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
585     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
586     EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
587     ASSERT_EQ(2, data.bucket_info_size());
588     EXPECT_EQ(1, data.bucket_info(0).count());
589     EXPECT_EQ(1, data.bucket_info(1).count());
590 
591     data = countMetrics.data(2);
592     ASSERT_EQ(1, data.slice_by_state_size());
593     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
594     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
595     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
596     ASSERT_EQ(2, data.bucket_info_size());
597     EXPECT_EQ(4, data.bucket_info(0).count());
598     EXPECT_EQ(2, data.bucket_info(1).count());
599 }
600 
601 /**
602 * Test a count metric that has one slice_by_state with a primary field.
603 
604 * Once the CountMetricProducer is initialized, it should have one
605 * MetricStateLink stored. State querying using a non-empty primary key
606 * should also work as intended.
607 */
TEST(CountMetricE2eTest,TestSlicedStateWithPrimaryFields)608 TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields) {
609     // Initialize config.
610     StatsdConfig config;
611 
612     auto appCrashMatcher =
613             CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED);
614     *config.add_atom_matcher() = appCrashMatcher;
615 
616     auto state = CreateUidProcessState();
617     *config.add_state() = state;
618 
619     // Create count metric that slices by uid process state.
620     int64_t metricId = 123456;
621     auto countMetric = config.add_count_metric();
622     countMetric->set_id(metricId);
623     countMetric->set_what(appCrashMatcher.id());
624     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
625     countMetric->add_slice_by_state(state.id());
626     *countMetric->mutable_dimensions_in_what() =
627             CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
628     MetricStateLink* stateLink = countMetric->add_state_link();
629     stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
630     auto fieldsInWhat = stateLink->mutable_fields_in_what();
631     *fieldsInWhat = CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
632     auto fieldsInState = stateLink->mutable_fields_in_state();
633     *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /*uid*/});
634 
635     // Initialize StatsLogProcessor.
636     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
637     const uint64_t bucketSizeNs =
638             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
639     int uid = 12345;
640     int64_t cfgId = 98765;
641     ConfigKey cfgKey(uid, cfgId);
642     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
643 
644     // Check that StateTrackers were initialized correctly.
645     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
646     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
647 
648     // Check that CountMetricProducer was initialized correctly.
649     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
650     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
651     EXPECT_TRUE(metricsManager->isConfigValid());
652     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
653     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
654     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
655     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), UID_PROCESS_STATE_ATOM_ID);
656     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
657     ASSERT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
658 
659     /*
660     NOTE: "1" or "2" represents the uid associated with the state/app crash event
661                bucket #1               bucket #2
662     |    1    2    3    4    5    6    7    8    9    10
663     |------------------------|-------------------------|--
664       1  1    1      1   1  2     1        1        2    (AppCrashEvents)
665      -----------------------------------------------------PROCESS STATE events
666            1               2                             (TopEvent = 1002)
667                        1             1                   (ForegroundServiceEvent = 1003)
668                                          2               (ImportantBackgroundEvent = 1006)
669        1          1                               1      (ImportantForegroundEvent = 1005)
670 
671     Based on the diagram above, an AppCrashEvent querying for process state value would return:
672     - StateTracker::kStateUnknown
673     - Important foreground
674     - Top
675     - Important foreground
676     - Foreground service
677     - Top (both the app crash and state still have matching uid = 2)
678 
679     - Foreground service
680     - Foreground service
681     - Important background
682     */
683     // Initialize log events - first bucket.
684     std::vector<std::unique_ptr<LogEvent>> events;
685     events.push_back(
686             CreateAppCrashOccurredEvent(bucketStartTimeNs + 20 * NS_PER_SEC, 1 /*uid*/));  // 0:30
687     events.push_back(CreateUidProcessStateChangedEvent(
688             bucketStartTimeNs + 30 * NS_PER_SEC, 1 /*uid*/,
689             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));  // 0:40
690     events.push_back(
691             CreateAppCrashOccurredEvent(bucketStartTimeNs + 60 * NS_PER_SEC, 1 /*uid*/));  // 1:10
692     events.push_back(CreateUidProcessStateChangedEvent(
693             bucketStartTimeNs + 90 * NS_PER_SEC, 1 /*uid*/,
694             android::app::ProcessStateEnum::PROCESS_STATE_TOP));  // 1:40
695     events.push_back(
696             CreateAppCrashOccurredEvent(bucketStartTimeNs + 120 * NS_PER_SEC, 1 /*uid*/));  // 2:10
697     events.push_back(CreateUidProcessStateChangedEvent(
698             bucketStartTimeNs + 150 * NS_PER_SEC, 1 /*uid*/,
699             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));  // 2:40
700     events.push_back(
701             CreateAppCrashOccurredEvent(bucketStartTimeNs + 200 * NS_PER_SEC, 1 /*uid*/));  // 3:30
702     events.push_back(CreateUidProcessStateChangedEvent(
703             bucketStartTimeNs + 210 * NS_PER_SEC, 1 /*uid*/,
704             android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE));  // 3:40
705     events.push_back(
706             CreateAppCrashOccurredEvent(bucketStartTimeNs + 250 * NS_PER_SEC, 1 /*uid*/));  // 4:20
707     events.push_back(CreateUidProcessStateChangedEvent(
708             bucketStartTimeNs + 280 * NS_PER_SEC, 2 /*uid*/,
709             android::app::ProcessStateEnum::PROCESS_STATE_TOP));  // 4:50
710     events.push_back(
711             CreateAppCrashOccurredEvent(bucketStartTimeNs + 285 * NS_PER_SEC, 2 /*uid*/));  // 4:55
712 
713     // Initialize log events - second bucket.
714     events.push_back(
715             CreateAppCrashOccurredEvent(bucketStartTimeNs + 360 * NS_PER_SEC, 1 /*uid*/));  // 6:10
716     events.push_back(CreateUidProcessStateChangedEvent(
717             bucketStartTimeNs + 390 * NS_PER_SEC, 1 /*uid*/,
718             android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE));  // 6:40
719     events.push_back(CreateUidProcessStateChangedEvent(
720             bucketStartTimeNs + 430 * NS_PER_SEC, 2 /*uid*/,
721             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND));  // 7:20
722     events.push_back(
723             CreateAppCrashOccurredEvent(bucketStartTimeNs + 440 * NS_PER_SEC, 1 /*uid*/));  // 7:30
724     events.push_back(CreateUidProcessStateChangedEvent(
725             bucketStartTimeNs + 540 * NS_PER_SEC, 1 /*uid*/,
726             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));  // 9:10
727     events.push_back(
728             CreateAppCrashOccurredEvent(bucketStartTimeNs + 570 * NS_PER_SEC, 2 /*uid*/));  // 9:40
729 
730     // Send log events to StatsLogProcessor.
731     for (auto& event : events) {
732         processor->OnLogEvent(event.get());
733     }
734 
735     // Check dump report.
736     vector<uint8_t> buffer;
737     ConfigMetricsReportList reports;
738     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
739                             FAST, &buffer);
740     ASSERT_GT(buffer.size(), 0);
741     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
742     backfillDimensionPath(&reports);
743     backfillStringInReport(&reports);
744     backfillStartEndTimestamp(&reports);
745 
746     ASSERT_EQ(1, reports.reports_size());
747     ASSERT_EQ(1, reports.reports(0).metrics_size());
748     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
749     StatsLogReport::CountMetricDataWrapper countMetrics;
750     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
751     ASSERT_EQ(6, countMetrics.data_size());
752 
753     // For each CountMetricData, check StateValue info is correct and buckets
754     // have correct counts.
755     auto data = countMetrics.data(0);
756     ASSERT_EQ(1, data.slice_by_state_size());
757     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
758     EXPECT_TRUE(data.slice_by_state(0).has_value());
759     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
760     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
761     ASSERT_EQ(1, data.bucket_info_size());
762     EXPECT_EQ(1, data.bucket_info(0).count());
763 
764     data = countMetrics.data(1);
765     ASSERT_EQ(1, data.slice_by_state_size());
766     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
767     EXPECT_TRUE(data.slice_by_state(0).has_value());
768     EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(0).value());
769     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
770     ASSERT_EQ(1, data.bucket_info_size());
771     EXPECT_EQ(1, data.bucket_info(0).count());
772 
773     data = countMetrics.data(2);
774     ASSERT_EQ(1, data.slice_by_state_size());
775     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
776     EXPECT_TRUE(data.slice_by_state(0).has_value());
777     EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(0).value());
778     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
779     ASSERT_EQ(2, data.bucket_info_size());
780     EXPECT_EQ(1, data.bucket_info(0).count());
781     EXPECT_EQ(2, data.bucket_info(1).count());
782 
783     data = countMetrics.data(3);
784     ASSERT_EQ(1, data.slice_by_state_size());
785     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
786     EXPECT_TRUE(data.slice_by_state(0).has_value());
787     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(0).value());
788     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
789     ASSERT_EQ(1, data.bucket_info_size());
790     EXPECT_EQ(2, data.bucket_info(0).count());
791 
792     data = countMetrics.data(4);
793     ASSERT_EQ(1, data.slice_by_state_size());
794     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
795     EXPECT_TRUE(data.slice_by_state(0).has_value());
796     EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(0).value());
797     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 2);
798     ASSERT_EQ(1, data.bucket_info_size());
799     EXPECT_EQ(1, data.bucket_info(0).count());
800 
801     data = countMetrics.data(5);
802     ASSERT_EQ(1, data.slice_by_state_size());
803     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
804     EXPECT_TRUE(data.slice_by_state(0).has_value());
805     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(0).value());
806     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 2);
807     ASSERT_EQ(1, data.bucket_info_size());
808     EXPECT_EQ(1, data.bucket_info(0).count());
809 }
810 
TEST(CountMetricE2eTest,TestMultipleSlicedStates)811 TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
812     // Initialize config.
813     StatsdConfig config;
814 
815     auto appCrashMatcher =
816             CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED);
817     *config.add_atom_matcher() = appCrashMatcher;
818 
819     int64_t screenOnId = 4444;
820     int64_t screenOffId = 9876;
821     auto state1 = CreateScreenStateWithOnOffMap(screenOnId, screenOffId);
822     *config.add_state() = state1;
823     auto state2 = CreateUidProcessState();
824     *config.add_state() = state2;
825 
826     // Create count metric that slices by screen state with on/off map and
827     // slices by uid process state.
828     int64_t metricId = 123456;
829     auto countMetric = config.add_count_metric();
830     countMetric->set_id(metricId);
831     countMetric->set_what(appCrashMatcher.id());
832     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
833     countMetric->add_slice_by_state(state1.id());
834     countMetric->add_slice_by_state(state2.id());
835     *countMetric->mutable_dimensions_in_what() =
836             CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
837     MetricStateLink* stateLink = countMetric->add_state_link();
838     stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
839     auto fieldsInWhat = stateLink->mutable_fields_in_what();
840     *fieldsInWhat = CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
841     auto fieldsInState = stateLink->mutable_fields_in_state();
842     *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /*uid*/});
843 
844     // Initialize StatsLogProcessor.
845     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
846     const uint64_t bucketSizeNs =
847             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
848     int uid = 12345;
849     int64_t cfgId = 98765;
850     ConfigKey cfgKey(uid, cfgId);
851     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
852 
853     // Check that StateTrackers were properly initialized.
854     EXPECT_EQ(2, StateManager::getInstance().getStateTrackersCount());
855     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
856     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
857 
858     // Check that CountMetricProducer was initialized correctly.
859     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
860     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
861     EXPECT_TRUE(metricsManager->isConfigValid());
862     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
863     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
864     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 2);
865     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
866     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(1), UID_PROCESS_STATE_ATOM_ID);
867     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 1);
868     ASSERT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
869 
870     StateMap map = state1.map();
871     for (auto group : map.group()) {
872         for (auto value : group.value()) {
873             EXPECT_EQ(metricProducer->mStateGroupMap.at(SCREEN_STATE_ATOM_ID).at(value),
874                       group.group_id());
875         }
876     }
877 
878     /*
879                  bucket #1                      bucket #2
880       |    1    2    3    4    5    6    7    8    9    10 (minutes)
881       |------------------------|------------------------|--
882         1  1    1     1    1  2     1        1         2   (AppCrashEvents)
883        ---------------------------------------------------SCREEN_OFF events
884              |                              |              (ScreenOffEvent = 1)
885          |              |                                  (ScreenDozeEvent = 3)
886        ---------------------------------------------------SCREEN_ON events
887                    |                              |        (ScreenOnEvent = 2)
888                                         |                  (ScreenOnSuspendEvent = 6)
889        ---------------------------------------------------PROCESS STATE events
890              1               2                             (TopEvent = 1002)
891                                       1                    (ForegroundServiceEvent = 1003)
892                                             2              (ImportantBackgroundEvent = 1006)
893        1          1                                   1    (ImportantForegroundEvent = 1005)
894 
895        Based on the diagram above, Screen State / Process State pairs for each
896        AppCrashEvent are:
897        - StateTracker::kStateUnknown / important foreground
898        - off / important foreground
899        - off / Top
900        - on / important foreground
901        - off / important foreground
902        - off / top
903 
904        - off / important foreground
905        - off / foreground service
906        - on / important background
907 
908       */
909     // Initialize log events - first bucket.
910     std::vector<std::unique_ptr<LogEvent>> events;
911     events.push_back(CreateUidProcessStateChangedEvent(
912             bucketStartTimeNs + 5 * NS_PER_SEC, 1 /*uid*/,
913             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));  // 0:15
914     events.push_back(
915             CreateAppCrashOccurredEvent(bucketStartTimeNs + 20 * NS_PER_SEC, 1 /*uid*/));  // 0:30
916     events.push_back(CreateScreenStateChangedEvent(
917             bucketStartTimeNs + 30 * NS_PER_SEC,
918             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 0:40
919     events.push_back(
920             CreateAppCrashOccurredEvent(bucketStartTimeNs + 60 * NS_PER_SEC, 1 /*uid*/));  // 1:10
921     events.push_back(CreateUidProcessStateChangedEvent(
922             bucketStartTimeNs + 90 * NS_PER_SEC, 1 /*uid*/,
923             android::app::ProcessStateEnum::PROCESS_STATE_TOP));  // 1:40
924     events.push_back(CreateScreenStateChangedEvent(
925             bucketStartTimeNs + 90 * NS_PER_SEC,
926             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 1:40
927     events.push_back(
928             CreateAppCrashOccurredEvent(bucketStartTimeNs + 120 * NS_PER_SEC, 1 /*uid*/));  // 2:10
929     events.push_back(CreateUidProcessStateChangedEvent(
930             bucketStartTimeNs + 150 * NS_PER_SEC, 1 /*uid*/,
931             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));  // 2:40
932     events.push_back(CreateScreenStateChangedEvent(
933             bucketStartTimeNs + 160 * NS_PER_SEC,
934             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 2:50
935     events.push_back(
936             CreateAppCrashOccurredEvent(bucketStartTimeNs + 200 * NS_PER_SEC, 1 /*uid*/));  // 3:30
937     events.push_back(CreateScreenStateChangedEvent(
938             bucketStartTimeNs + 210 * NS_PER_SEC,
939             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 3:40
940     events.push_back(
941             CreateAppCrashOccurredEvent(bucketStartTimeNs + 250 * NS_PER_SEC, 1 /*uid*/));  // 4:20
942     events.push_back(CreateUidProcessStateChangedEvent(
943             bucketStartTimeNs + 280 * NS_PER_SEC, 2 /*uid*/,
944             android::app::ProcessStateEnum::PROCESS_STATE_TOP));  // 4:50
945     events.push_back(
946             CreateAppCrashOccurredEvent(bucketStartTimeNs + 285 * NS_PER_SEC, 2 /*uid*/));  // 4:55
947 
948     // Initialize log events - second bucket.
949     events.push_back(
950             CreateAppCrashOccurredEvent(bucketStartTimeNs + 360 * NS_PER_SEC, 1 /*uid*/));  // 6:10
951     events.push_back(CreateUidProcessStateChangedEvent(
952             bucketStartTimeNs + 380 * NS_PER_SEC, 1 /*uid*/,
953             android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE));  // 6:30
954     events.push_back(CreateScreenStateChangedEvent(
955             bucketStartTimeNs + 390 * NS_PER_SEC,
956             android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND));  // 6:40
957     events.push_back(CreateUidProcessStateChangedEvent(
958             bucketStartTimeNs + 420 * NS_PER_SEC, 2 /*uid*/,
959             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND));  // 7:10
960     events.push_back(CreateScreenStateChangedEvent(
961             bucketStartTimeNs + 440 * NS_PER_SEC,
962             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 7:30
963     events.push_back(
964             CreateAppCrashOccurredEvent(bucketStartTimeNs + 450 * NS_PER_SEC, 1 /*uid*/));  // 7:40
965     events.push_back(CreateScreenStateChangedEvent(
966             bucketStartTimeNs + 520 * NS_PER_SEC,
967             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 8:50
968     events.push_back(CreateUidProcessStateChangedEvent(
969             bucketStartTimeNs + 540 * NS_PER_SEC, 1 /*uid*/,
970             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));  // 9:10
971     events.push_back(
972             CreateAppCrashOccurredEvent(bucketStartTimeNs + 570 * NS_PER_SEC, 2 /*uid*/));  // 9:40
973 
974     // Send log events to StatsLogProcessor.
975     for (auto& event : events) {
976         processor->OnLogEvent(event.get());
977     }
978 
979     // Check dump report.
980     vector<uint8_t> buffer;
981     ConfigMetricsReportList reports;
982     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
983                             FAST, &buffer);
984     ASSERT_GT(buffer.size(), 0);
985     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
986     backfillDimensionPath(&reports);
987     backfillStringInReport(&reports);
988     backfillStartEndTimestamp(&reports);
989 
990     ASSERT_EQ(1, reports.reports_size());
991     ASSERT_EQ(1, reports.reports(0).metrics_size());
992     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
993     StatsLogReport::CountMetricDataWrapper countMetrics;
994     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
995     ASSERT_EQ(7, countMetrics.data_size());
996 
997     // For each CountMetricData, check StateValue info is correct and buckets
998     // have correct counts.
999     auto data = countMetrics.data(0);
1000     ASSERT_EQ(2, data.slice_by_state_size());
1001     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1002     EXPECT_TRUE(data.slice_by_state(0).has_value());
1003     EXPECT_EQ(-1, data.slice_by_state(0).value());
1004     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
1005     EXPECT_TRUE(data.slice_by_state(1).has_value());
1006     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
1007     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
1008     ASSERT_EQ(1, data.bucket_info_size());
1009     EXPECT_EQ(1, data.bucket_info(0).count());
1010 
1011     data = countMetrics.data(1);
1012     ASSERT_EQ(2, data.slice_by_state_size());
1013     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1014     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
1015     EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
1016     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
1017     EXPECT_TRUE(data.slice_by_state(1).has_value());
1018     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
1019     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
1020     ASSERT_EQ(1, data.bucket_info_size());
1021     EXPECT_EQ(1, data.bucket_info(0).count());
1022 
1023     data = countMetrics.data(2);
1024     ASSERT_EQ(2, data.slice_by_state_size());
1025     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1026     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
1027     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
1028     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
1029     EXPECT_TRUE(data.slice_by_state(1).has_value());
1030     EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(1).value());
1031     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
1032     ASSERT_EQ(1, data.bucket_info_size());
1033     EXPECT_EQ(1, data.bucket_info(0).count());
1034 
1035     data = countMetrics.data(3);
1036     ASSERT_EQ(2, data.slice_by_state_size());
1037     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1038     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
1039     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
1040     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
1041     EXPECT_TRUE(data.slice_by_state(1).has_value());
1042     EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(1).value());
1043     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
1044     ASSERT_EQ(1, data.bucket_info_size());
1045     EXPECT_EQ(1, data.bucket_info(0).count());
1046 
1047     data = countMetrics.data(4);
1048     ASSERT_EQ(2, data.slice_by_state_size());
1049     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1050     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
1051     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
1052     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
1053     EXPECT_TRUE(data.slice_by_state(1).has_value());
1054     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
1055     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
1056     ASSERT_EQ(2, data.bucket_info_size());
1057     EXPECT_EQ(2, data.bucket_info(0).count());
1058     EXPECT_EQ(1, data.bucket_info(1).count());
1059 
1060     data = countMetrics.data(5);
1061     ASSERT_EQ(2, data.slice_by_state_size());
1062     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1063     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
1064     EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
1065     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
1066     EXPECT_TRUE(data.slice_by_state(1).has_value());
1067     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(1).value());
1068     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 2);
1069     ASSERT_EQ(1, data.bucket_info_size());
1070     EXPECT_EQ(1, data.bucket_info(0).count());
1071 
1072     data = countMetrics.data(6);
1073     ASSERT_EQ(2, data.slice_by_state_size());
1074     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1075     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
1076     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
1077     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
1078     EXPECT_TRUE(data.slice_by_state(1).has_value());
1079     EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(1).value());
1080     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 2);
1081     ASSERT_EQ(1, data.bucket_info_size());
1082     EXPECT_EQ(1, data.bucket_info(0).count());
1083 }
1084 
TEST(CountMetricE2eTest,TestUploadThreshold)1085 TEST(CountMetricE2eTest, TestUploadThreshold) {
1086     // Initialize config.
1087     StatsdConfig config;
1088 
1089     auto appCrashMatcher = CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED);
1090     *config.add_atom_matcher() = appCrashMatcher;
1091 
1092     int64_t thresholdCount = 2;
1093     UploadThreshold threshold;
1094     threshold.set_gt_int(thresholdCount);
1095 
1096     int64_t metricId = 123456;
1097     CountMetric countMetric = createCountMetric("COUNT", appCrashMatcher.id(), nullopt, {});
1098     *countMetric.mutable_dimensions_in_what() =
1099             CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
1100     *countMetric.mutable_threshold() = threshold;
1101     *config.add_count_metric() = countMetric;
1102 
1103     // Initialize StatsLogProcessor.
1104     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1105     const uint64_t bucketSizeNs =
1106             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
1107     int uid = 12345;
1108     int64_t cfgId = 98765;
1109     ConfigKey cfgKey(uid, cfgId);
1110     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1111 
1112     int appUid1 = 1;
1113     int appUid2 = 2;
1114     std::vector<std::unique_ptr<LogEvent>> events;
1115     events.push_back(
1116             CreateAppCrashOccurredEvent(bucketStartTimeNs + 20 * NS_PER_SEC, appUid1));  // 0:30
1117     events.push_back(
1118             CreateAppCrashOccurredEvent(bucketStartTimeNs + 40 * NS_PER_SEC, appUid2));  // 0:50
1119     events.push_back(
1120             CreateAppCrashOccurredEvent(bucketStartTimeNs + 60 * NS_PER_SEC, appUid1));  // 1:10
1121     events.push_back(
1122             CreateAppCrashOccurredEvent(bucketStartTimeNs + 65 * NS_PER_SEC, appUid1));  // 1:15
1123 
1124     // Send log events to StatsLogProcessor.
1125     for (auto& event : events) {
1126         processor->OnLogEvent(event.get());
1127     }
1128 
1129     // Check dump report.
1130     vector<uint8_t> buffer;
1131     ConfigMetricsReportList reports;
1132     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
1133                             FAST, &buffer);
1134     ASSERT_GT(buffer.size(), 0);
1135     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1136     backfillDimensionPath(&reports);
1137     backfillStringInReport(&reports);
1138     backfillStartEndTimestamp(&reports);
1139 
1140     ASSERT_EQ(1, reports.reports_size());
1141     ASSERT_EQ(1, reports.reports(0).metrics_size());
1142     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
1143     StatsLogReport::CountMetricDataWrapper countMetrics;
1144     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
1145     ASSERT_EQ(1, countMetrics.data_size());
1146 
1147     CountMetricData data = countMetrics.data(0);
1148 
1149     // Uid 1 reports a count greater than the threshold.
1150     // Uid 2 is dropped because the count was less than the threshold.
1151     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, appUid1);
1152     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1153                         3);
1154 }
1155 
TEST(CountMetricE2eTest,TestRepeatedFieldsAndEmptyArrays)1156 TEST(CountMetricE2eTest, TestRepeatedFieldsAndEmptyArrays) {
1157     StatsdConfig config;
1158 
1159     AtomMatcher testAtomReportedAtomMatcher =
1160             CreateSimpleAtomMatcher("TestAtomReportedMatcher", util::TEST_ATOM_REPORTED);
1161     *config.add_atom_matcher() = testAtomReportedAtomMatcher;
1162 
1163     int64_t metricId = 123456;
1164     CountMetric* countMetric = config.add_count_metric();
1165     countMetric->set_id(metricId);
1166     countMetric->set_what(testAtomReportedAtomMatcher.id());
1167     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
1168 
1169     // Initialize StatsLogProcessor.
1170     ConfigKey cfgKey(123, 987);
1171     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1172     const uint64_t bucketSizeNs =
1173             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
1174     sp<StatsLogProcessor> processor =
1175             CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1176 
1177     vector<int> intArray = {3, 6};
1178     vector<int64_t> longArray = {1000L, 10002L};
1179     vector<float> floatArray = {0.3f, 0.09f};
1180     vector<string> stringArray = {"str1", "str2"};
1181     int boolArrayLength = 2;
1182     bool boolArray[boolArrayLength];
1183     boolArray[0] = 1;
1184     boolArray[1] = 0;
1185     vector<int> enumArray = {TestAtomReported::ON, TestAtomReported::OFF};
1186 
1187     std::vector<std::unique_ptr<LogEvent>> events;
1188     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1189             bucketStartTimeNs + 10 * NS_PER_SEC, intArray, longArray, floatArray, stringArray,
1190             boolArray, boolArrayLength, enumArray));
1191     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1192             bucketStartTimeNs + 20 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, {}));
1193 
1194     // Send log events to StatsLogProcessor.
1195     for (auto& event : events) {
1196         processor->OnLogEvent(event.get());
1197     }
1198 
1199     // Check dump report.
1200     vector<uint8_t> buffer;
1201     ConfigMetricsReportList reports;
1202     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
1203                             FAST, &buffer);
1204     ASSERT_GT(buffer.size(), 0);
1205     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1206     backfillDimensionPath(&reports);
1207     backfillStringInReport(&reports);
1208     backfillStartEndTimestamp(&reports);
1209 
1210     ASSERT_EQ(1, reports.reports_size());
1211     ASSERT_EQ(1, reports.reports(0).metrics_size());
1212     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
1213     StatsLogReport::CountMetricDataWrapper countMetrics;
1214     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
1215     ASSERT_EQ(1, countMetrics.data_size());
1216 
1217     CountMetricData data = countMetrics.data(0);
1218     ASSERT_EQ(1, data.bucket_info_size());
1219     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1220                         2);
1221 }
1222 
TEST(CountMetricE2eTest,TestMatchRepeatedFieldPositionAny)1223 TEST(CountMetricE2eTest, TestMatchRepeatedFieldPositionAny) {
1224     StatsdConfig config;
1225 
1226     AtomMatcher testAtomReportedStateAnyOnAtomMatcher =
1227             CreateTestAtomRepeatedStateAnyOnAtomMatcher();
1228     *config.add_atom_matcher() = testAtomReportedStateAnyOnAtomMatcher;
1229 
1230     int64_t metricId = 123456;
1231     CountMetric* countMetric = config.add_count_metric();
1232     countMetric->set_id(metricId);
1233     countMetric->set_what(testAtomReportedStateAnyOnAtomMatcher.id());
1234     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
1235 
1236     // Initialize StatsLogProcessor.
1237     ConfigKey cfgKey(123, 987);
1238     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1239     const uint64_t bucketSizeNs =
1240             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
1241     sp<StatsLogProcessor> processor =
1242             CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1243 
1244     vector<int> enumArrayOnFirst = {TestAtomReported::ON, TestAtomReported::OFF};
1245     vector<int> enumArrayOnLast = {TestAtomReported::OFF, TestAtomReported::ON};
1246     vector<int> enumArrayNoOn = {TestAtomReported::OFF, TestAtomReported::OFF};
1247 
1248     std::vector<std::unique_ptr<LogEvent>> events;
1249     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1250             bucketStartTimeNs + 20 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOnFirst));
1251     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1252             bucketStartTimeNs + 40 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayNoOn));
1253     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1254             bucketStartTimeNs + 60 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOnLast));
1255     // No matching is done on empty array.
1256     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1257             bucketStartTimeNs + 80 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, {}));
1258 
1259     // Send log events to StatsLogProcessor.
1260     for (auto& event : events) {
1261         processor->OnLogEvent(event.get());
1262     }
1263 
1264     // Check dump report.
1265     vector<uint8_t> buffer;
1266     ConfigMetricsReportList reports;
1267     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
1268                             FAST, &buffer);
1269     ASSERT_GT(buffer.size(), 0);
1270     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1271     backfillDimensionPath(&reports);
1272     backfillStringInReport(&reports);
1273     backfillStartEndTimestamp(&reports);
1274 
1275     ASSERT_EQ(1, reports.reports_size());
1276     ASSERT_EQ(1, reports.reports(0).metrics_size());
1277     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
1278     StatsLogReport::CountMetricDataWrapper countMetrics;
1279     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
1280     ASSERT_EQ(1, countMetrics.data_size());
1281 
1282     CountMetricData data = countMetrics.data(0);
1283     ASSERT_EQ(1, data.bucket_info_size());
1284     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1285                         2);
1286 }
1287 
TEST(CountMetricE2eTest,TestRepeatedFieldDimension_PositionFirst)1288 TEST(CountMetricE2eTest, TestRepeatedFieldDimension_PositionFirst) {
1289     StatsdConfig config;
1290 
1291     AtomMatcher testAtomReportedAtomMatcher =
1292             CreateSimpleAtomMatcher("TestAtomReportedMatcher", util::TEST_ATOM_REPORTED);
1293     *config.add_atom_matcher() = testAtomReportedAtomMatcher;
1294 
1295     int64_t metricId = 123456;
1296     CountMetric* countMetric = config.add_count_metric();
1297     countMetric->set_id(metricId);
1298     countMetric->set_what(testAtomReportedAtomMatcher.id());
1299     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
1300     *countMetric->mutable_dimensions_in_what() = CreateRepeatedDimensions(
1301             util::TEST_ATOM_REPORTED, {14 /*repeated_enum_field*/}, {Position::FIRST});
1302 
1303     // Initialize StatsLogProcessor.
1304     ConfigKey cfgKey(2000, 921);
1305     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1306     const uint64_t bucketSizeNs =
1307             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
1308     sp<StatsLogProcessor> processor =
1309             CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1310 
1311     vector<int> enumArrayOnOff = {TestAtomReported::ON, TestAtomReported::OFF};
1312     vector<int> enumArrayOnOn = {TestAtomReported::ON, TestAtomReported::ON};
1313     vector<int> enumArrayOffOn = {TestAtomReported::OFF, TestAtomReported::ON};
1314 
1315     std::vector<std::unique_ptr<LogEvent>> events;
1316     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1317             bucketStartTimeNs + 20 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOnOff));
1318     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1319             bucketStartTimeNs + 40 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOffOn));
1320     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1321             bucketStartTimeNs + 60 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOnOn));
1322     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1323             bucketStartTimeNs + 80 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, {}));
1324 
1325     // Send log events to StatsLogProcessor.
1326     for (auto& event : events) {
1327         processor->OnLogEvent(event.get());
1328     }
1329 
1330     // Check dump report.
1331     vector<uint8_t> buffer;
1332     ConfigMetricsReportList reports;
1333     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
1334                             FAST, &buffer);
1335     ASSERT_GT(buffer.size(), 0);
1336     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1337     backfillStringInReport(&reports);
1338     backfillStartEndTimestamp(&reports);
1339 
1340     ASSERT_EQ(1, reports.reports_size());
1341     ASSERT_EQ(1, reports.reports(0).metrics_size());
1342     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
1343     StatsLogReport::CountMetricDataWrapper countMetrics;
1344     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
1345     ASSERT_EQ(3, countMetrics.data_size());
1346 
1347     // Empty dimensions case.
1348     CountMetricData data = countMetrics.data(0);
1349     ASSERT_EQ(1, data.bucket_info_size());
1350     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1351                         1);
1352     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 0);
1353 
1354     data = countMetrics.data(1);
1355     ASSERT_EQ(1, data.bucket_info_size());
1356     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1357                         1);
1358     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1359     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
1360     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 14);
1361     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(),
1362               TestAtomReported::OFF);
1363 
1364     data = countMetrics.data(2);
1365     ASSERT_EQ(1, data.bucket_info_size());
1366     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1367                         2);
1368     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1369     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
1370     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 14);
1371     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(),
1372               TestAtomReported::ON);
1373 }
1374 
TEST(CountMetricE2eTest,TestRepeatedFieldDimension_PositionLast)1375 TEST(CountMetricE2eTest, TestRepeatedFieldDimension_PositionLast) {
1376     StatsdConfig config;
1377 
1378     AtomMatcher testAtomReportedAtomMatcher =
1379             CreateSimpleAtomMatcher("TestAtomReportedMatcher", util::TEST_ATOM_REPORTED);
1380     *config.add_atom_matcher() = testAtomReportedAtomMatcher;
1381 
1382     int64_t metricId = 123456;
1383     CountMetric* countMetric = config.add_count_metric();
1384     countMetric->set_id(metricId);
1385     countMetric->set_what(testAtomReportedAtomMatcher.id());
1386     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
1387     *countMetric->mutable_dimensions_in_what() = CreateRepeatedDimensions(
1388             util::TEST_ATOM_REPORTED, {14 /*repeated_enum_field*/}, {Position::LAST});
1389 
1390     // Initialize StatsLogProcessor.
1391     ConfigKey cfgKey(2000, 921);
1392     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1393     const uint64_t bucketSizeNs =
1394             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
1395     sp<StatsLogProcessor> processor =
1396             CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1397 
1398     vector<int> enumArrayOnOff = {TestAtomReported::ON, TestAtomReported::OFF};
1399     vector<int> enumArrayOffOff = {TestAtomReported::OFF, TestAtomReported::OFF};
1400     vector<int> enumArrayOffOn = {TestAtomReported::OFF, TestAtomReported::ON};
1401 
1402     std::vector<std::unique_ptr<LogEvent>> events;
1403     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1404             bucketStartTimeNs + 20 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOnOff));
1405     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1406             bucketStartTimeNs + 40 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOffOff));
1407     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1408             bucketStartTimeNs + 60 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOffOn));
1409 
1410     // Send log events to StatsLogProcessor.
1411     for (auto& event : events) {
1412         processor->OnLogEvent(event.get());
1413     }
1414 
1415     // Check dump report.
1416     vector<uint8_t> buffer;
1417     ConfigMetricsReportList reports;
1418     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
1419                             FAST, &buffer);
1420     ASSERT_GT(buffer.size(), 0);
1421     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1422     backfillStringInReport(&reports);
1423     backfillStartEndTimestamp(&reports);
1424 
1425     ASSERT_EQ(1, reports.reports_size());
1426     ASSERT_EQ(1, reports.reports(0).metrics_size());
1427     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
1428     StatsLogReport::CountMetricDataWrapper countMetrics;
1429     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
1430     ASSERT_EQ(2, countMetrics.data_size());
1431 
1432     CountMetricData data = countMetrics.data(0);
1433     ASSERT_EQ(1, data.bucket_info_size());
1434     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1435                         2);
1436     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1437     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
1438     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 14);
1439     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(),
1440               TestAtomReported::OFF);
1441 
1442     data = countMetrics.data(1);
1443     ASSERT_EQ(1, data.bucket_info_size());
1444     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1445                         1);
1446     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1447     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
1448     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 14);
1449     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(),
1450               TestAtomReported::ON);
1451 }
1452 
TEST(CountMetricE2eTest,TestRepeatedFieldDimension_PositionAll)1453 TEST(CountMetricE2eTest, TestRepeatedFieldDimension_PositionAll) {
1454     StatsdConfig config;
1455 
1456     AtomMatcher testAtomReportedAtomMatcher =
1457             CreateSimpleAtomMatcher("TestAtomReportedMatcher", util::TEST_ATOM_REPORTED);
1458     *config.add_atom_matcher() = testAtomReportedAtomMatcher;
1459 
1460     int64_t metricId = 123456;
1461     CountMetric* countMetric = config.add_count_metric();
1462     countMetric->set_id(metricId);
1463     countMetric->set_what(testAtomReportedAtomMatcher.id());
1464     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
1465     *countMetric->mutable_dimensions_in_what() = CreateRepeatedDimensions(
1466             util::TEST_ATOM_REPORTED, {14 /*repeated_enum_field*/}, {Position::ALL});
1467 
1468     // Initialize StatsLogProcessor.
1469     ConfigKey cfgKey(2000, 921);
1470     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1471     const uint64_t bucketSizeNs =
1472             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
1473     sp<StatsLogProcessor> processor =
1474             CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1475 
1476     vector<int> enumArrayOnOff = {TestAtomReported::ON, TestAtomReported::OFF};
1477     vector<int> enumArrayOnOn = {TestAtomReported::ON, TestAtomReported::ON};
1478     vector<int> enumArrayOffOn = {TestAtomReported::OFF, TestAtomReported::ON};
1479 
1480     std::vector<std::unique_ptr<LogEvent>> events;
1481     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1482             bucketStartTimeNs + 20 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOnOff));
1483     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1484             bucketStartTimeNs + 40 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOffOn));
1485     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1486             bucketStartTimeNs + 60 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOnOn));
1487     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1488             bucketStartTimeNs + 40 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOffOn));
1489     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1490             bucketStartTimeNs + 20 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOnOff));
1491     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1492             bucketStartTimeNs + 40 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOffOn));
1493 
1494     // Send log events to StatsLogProcessor.
1495     for (auto& event : events) {
1496         processor->OnLogEvent(event.get());
1497     }
1498 
1499     // Check dump report.
1500     vector<uint8_t> buffer;
1501     ConfigMetricsReportList reports;
1502     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
1503                             FAST, &buffer);
1504     ASSERT_GT(buffer.size(), 0);
1505     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1506     // Don't need to backfill dimension path because dimensions with position ALL are not encoded
1507     // with the path format.
1508     backfillStringInReport(&reports);
1509     backfillStartEndTimestamp(&reports);
1510 
1511     ASSERT_EQ(1, reports.reports_size());
1512     ASSERT_EQ(1, reports.reports(0).metrics_size());
1513     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
1514     StatsLogReport::CountMetricDataWrapper countMetrics;
1515     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
1516     ASSERT_EQ(3, countMetrics.data_size());
1517 
1518     CountMetricData data = countMetrics.data(0);
1519     ASSERT_EQ(1, data.bucket_info_size());
1520     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1521                         3);
1522     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1523     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 2);
1524     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 14);
1525     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(),
1526               TestAtomReported::OFF);
1527     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).field(), 14);
1528     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).value_int(),
1529               TestAtomReported::ON);
1530 
1531     data = countMetrics.data(1);
1532     ASSERT_EQ(1, data.bucket_info_size());
1533     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1534                         2);
1535     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1536     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 2);
1537     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 14);
1538     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(),
1539               TestAtomReported::ON);
1540     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).field(), 14);
1541     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).value_int(),
1542               TestAtomReported::OFF);
1543 
1544     data = countMetrics.data(2);
1545     ASSERT_EQ(1, data.bucket_info_size());
1546     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1547                         1);
1548     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1549     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 2);
1550     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 14);
1551     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(),
1552               TestAtomReported::ON);
1553     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).field(), 14);
1554     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).value_int(),
1555               TestAtomReported::ON);
1556 }
1557 
TEST(CountMetricE2eTest,TestMultipleRepeatedFieldDimensions_PositionFirst)1558 TEST(CountMetricE2eTest, TestMultipleRepeatedFieldDimensions_PositionFirst) {
1559     StatsdConfig config;
1560 
1561     AtomMatcher testAtomReportedAtomMatcher =
1562             CreateSimpleAtomMatcher("TestAtomReportedMatcher", util::TEST_ATOM_REPORTED);
1563     *config.add_atom_matcher() = testAtomReportedAtomMatcher;
1564 
1565     int64_t metricId = 123456;
1566     CountMetric* countMetric = config.add_count_metric();
1567     countMetric->set_id(metricId);
1568     countMetric->set_what(testAtomReportedAtomMatcher.id());
1569     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
1570     *countMetric->mutable_dimensions_in_what() = CreateRepeatedDimensions(
1571             util::TEST_ATOM_REPORTED, {9 /*repeated_int_field*/, 14 /*repeated_enum_field*/},
1572             {Position::FIRST, Position::FIRST});
1573 
1574     // Initialize StatsLogProcessor.
1575     ConfigKey cfgKey(2000, 921);
1576     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1577     const uint64_t bucketSizeNs =
1578             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
1579     sp<StatsLogProcessor> processor =
1580             CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1581 
1582     vector<int> intArrayThree = {3, 6, 9};
1583     vector<int> intArraySix = {6, 9};
1584     vector<int> enumArrayOn = {TestAtomReported::ON, TestAtomReported::OFF};
1585 
1586     std::vector<std::unique_ptr<LogEvent>> events;
1587     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1588             bucketStartTimeNs + 20 * NS_PER_SEC, intArrayThree, {}, {}, {}, {}, 0, enumArrayOn));
1589     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1590             bucketStartTimeNs + 40 * NS_PER_SEC, intArraySix, {}, {}, {}, {}, 0, enumArrayOn));
1591     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1592             bucketStartTimeNs + 60 * NS_PER_SEC, intArrayThree, {}, {}, {}, {}, 0, enumArrayOn));
1593     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1594             bucketStartTimeNs + 80 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArrayOn));
1595     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1596             bucketStartTimeNs + 100 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, {}));
1597     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1598             bucketStartTimeNs + 120 * NS_PER_SEC, intArraySix, {}, {}, {}, {}, 0, {}));
1599 
1600     // Send log events to StatsLogProcessor.
1601     for (auto& event : events) {
1602         processor->OnLogEvent(event.get());
1603     }
1604 
1605     // Check dump report.
1606     vector<uint8_t> buffer;
1607     ConfigMetricsReportList reports;
1608     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
1609                             FAST, &buffer);
1610     ASSERT_GT(buffer.size(), 0);
1611     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1612     backfillStringInReport(&reports);
1613     backfillStartEndTimestamp(&reports);
1614 
1615     ASSERT_EQ(1, reports.reports_size());
1616     ASSERT_EQ(1, reports.reports(0).metrics_size());
1617     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
1618     StatsLogReport::CountMetricDataWrapper countMetrics;
1619     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
1620     ASSERT_EQ(5, countMetrics.data_size());
1621 
1622     CountMetricData data = countMetrics.data(0);
1623     ASSERT_EQ(1, data.bucket_info_size());
1624     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1625                         1);
1626     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 0);
1627 
1628     data = countMetrics.data(1);
1629     ASSERT_EQ(1, data.bucket_info_size());
1630     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1631                         1);
1632     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1633     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
1634     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 9);
1635     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 6);
1636 
1637     data = countMetrics.data(2);
1638     ASSERT_EQ(1, data.bucket_info_size());
1639     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1640                         1);
1641     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1642     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
1643     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 14);
1644     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(),
1645               TestAtomReported::ON);
1646 
1647     data = countMetrics.data(3);
1648     ASSERT_EQ(1, data.bucket_info_size());
1649     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1650                         2);
1651     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1652     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 2);
1653     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 9);
1654     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 3);
1655     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).field(), 14);
1656     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).value_int(),
1657               TestAtomReported::ON);
1658 
1659     data = countMetrics.data(4);
1660     ASSERT_EQ(1, data.bucket_info_size());
1661     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1662                         1);
1663     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1664     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 2);
1665     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 9);
1666     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 6);
1667     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).field(), 14);
1668     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).value_int(),
1669               TestAtomReported::ON);
1670 }
1671 
TEST(CountMetricE2eTest,TestMultipleRepeatedFieldDimensions_PositionAll)1672 TEST(CountMetricE2eTest, TestMultipleRepeatedFieldDimensions_PositionAll) {
1673     StatsdConfig config;
1674 
1675     AtomMatcher testAtomReportedAtomMatcher =
1676             CreateSimpleAtomMatcher("TestAtomReportedMatcher", util::TEST_ATOM_REPORTED);
1677     *config.add_atom_matcher() = testAtomReportedAtomMatcher;
1678 
1679     int64_t metricId = 123456;
1680     CountMetric* countMetric = config.add_count_metric();
1681     countMetric->set_id(metricId);
1682     countMetric->set_what(testAtomReportedAtomMatcher.id());
1683     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
1684     *countMetric->mutable_dimensions_in_what() = CreateRepeatedDimensions(
1685             util::TEST_ATOM_REPORTED, {9 /*repeated_int_field*/, 14 /*repeated_enum_field*/},
1686             {Position::ALL, Position::ALL});
1687 
1688     // Initialize StatsLogProcessor.
1689     ConfigKey cfgKey(2000, 921);
1690     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1691     const uint64_t bucketSizeNs =
1692             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
1693     sp<StatsLogProcessor> processor =
1694             CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1695 
1696     vector<int> intArray1 = {3, 6};
1697     vector<int> intArray2 = {6, 9};
1698     vector<int> enumArray = {TestAtomReported::ON, TestAtomReported::OFF};
1699 
1700     std::vector<std::unique_ptr<LogEvent>> events;
1701     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1702             bucketStartTimeNs + 20 * NS_PER_SEC, intArray1, {}, {}, {}, {}, 0, enumArray));
1703     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1704             bucketStartTimeNs + 40 * NS_PER_SEC, intArray2, {}, {}, {}, {}, 0, enumArray));
1705     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1706             bucketStartTimeNs + 80 * NS_PER_SEC, intArray1, {}, {}, {}, {}, 0, enumArray));
1707     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1708             bucketStartTimeNs + 100 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, enumArray));
1709     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1710             bucketStartTimeNs + 120 * NS_PER_SEC, {}, {}, {}, {}, {}, 0, {}));
1711     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1712             bucketStartTimeNs + 140 * NS_PER_SEC, intArray2, {}, {}, {}, {}, 0, {}));
1713 
1714     // Send log events to StatsLogProcessor.
1715     for (auto& event : events) {
1716         processor->OnLogEvent(event.get());
1717     }
1718 
1719     // Check dump report.
1720     vector<uint8_t> buffer;
1721     ConfigMetricsReportList reports;
1722     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
1723                             FAST, &buffer);
1724     ASSERT_GT(buffer.size(), 0);
1725     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1726     backfillStringInReport(&reports);
1727     backfillStartEndTimestamp(&reports);
1728 
1729     ASSERT_EQ(1, reports.reports_size());
1730     ASSERT_EQ(1, reports.reports(0).metrics_size());
1731     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
1732     StatsLogReport::CountMetricDataWrapper countMetrics;
1733     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
1734     ASSERT_EQ(5, countMetrics.data_size());
1735 
1736     CountMetricData data = countMetrics.data(0);
1737     ASSERT_EQ(1, data.bucket_info_size());
1738     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1739                         1);
1740     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 0);
1741 
1742     data = countMetrics.data(1);
1743     ASSERT_EQ(1, data.bucket_info_size());
1744     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1745                         1);
1746     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1747     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 2);
1748     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 9);
1749     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 6);
1750     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).field(), 9);
1751     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).value_int(), 9);
1752 
1753     data = countMetrics.data(2);
1754     ASSERT_EQ(1, data.bucket_info_size());
1755     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1756                         1);
1757     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1758     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 2);
1759     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 14);
1760     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(),
1761               TestAtomReported::ON);
1762     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).field(), 14);
1763     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).value_int(),
1764               TestAtomReported::OFF);
1765 
1766     data = countMetrics.data(3);
1767     ASSERT_EQ(1, data.bucket_info_size());
1768     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1769                         2);
1770     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1771     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 4);
1772     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 9);
1773     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 3);
1774     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).field(), 9);
1775     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).value_int(), 6);
1776     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(2).field(), 14);
1777     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(2).value_int(),
1778               TestAtomReported::ON);
1779     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(3).field(), 14);
1780     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(3).value_int(),
1781               TestAtomReported::OFF);
1782 
1783     data = countMetrics.data(4);
1784     ASSERT_EQ(1, data.bucket_info_size());
1785     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1786                         1);
1787     EXPECT_EQ(util::TEST_ATOM_REPORTED, data.dimensions_in_what().field());
1788     ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 4);
1789     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 9);
1790     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 6);
1791     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).field(), 9);
1792     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(1).value_int(), 9);
1793     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(2).field(), 14);
1794     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(2).value_int(),
1795               TestAtomReported::ON);
1796     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(3).field(), 14);
1797     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(3).value_int(),
1798               TestAtomReported::OFF);
1799 }
1800 
TEST(CountMetricE2eTest,TestConditionSlicedByRepeatedUidWithUidDimension)1801 TEST(CountMetricE2eTest, TestConditionSlicedByRepeatedUidWithUidDimension) {
1802     StatsdConfig config;
1803 
1804     AtomMatcher uidProcessStateChangedAtomMatcher = CreateUidProcessStateChangedAtomMatcher();
1805     AtomMatcher repeatedStateFirstOffAtomMatcher = CreateTestAtomRepeatedStateFirstOffAtomMatcher();
1806     AtomMatcher repeatedStateFirstOnAtomMatcher = CreateTestAtomRepeatedStateFirstOnAtomMatcher();
1807     *config.add_atom_matcher() = uidProcessStateChangedAtomMatcher;
1808     *config.add_atom_matcher() = repeatedStateFirstOffAtomMatcher;
1809     *config.add_atom_matcher() = repeatedStateFirstOnAtomMatcher;
1810 
1811     Predicate testAtomRepeatedStateFirstOffPerUidPredicate =
1812             CreateTestAtomRepeatedStateFirstOffPredicate();
1813     FieldMatcher* dimensions =
1814             testAtomRepeatedStateFirstOffPerUidPredicate.mutable_simple_predicate()
1815                     ->mutable_dimensions();
1816     *dimensions = CreateRepeatedDimensions(util::TEST_ATOM_REPORTED, {9 /* repeated uid*/},
1817                                            {Position::FIRST});
1818     *config.add_predicate() = testAtomRepeatedStateFirstOffPerUidPredicate;
1819 
1820     int64_t metricId = 123456;
1821     CountMetric* countMetric = config.add_count_metric();
1822     countMetric->set_id(metricId);
1823     countMetric->set_what(uidProcessStateChangedAtomMatcher.id());
1824     countMetric->set_condition(testAtomRepeatedStateFirstOffPerUidPredicate.id());
1825     countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
1826     *countMetric->mutable_dimensions_in_what() =
1827             CreateDimensions(util::UID_PROCESS_STATE_CHANGED, {1 /*uid*/});
1828     MetricConditionLink* links = countMetric->add_links();
1829     links->set_condition(testAtomRepeatedStateFirstOffPerUidPredicate.id());
1830     *links->mutable_fields_in_what() =
1831             CreateDimensions(util::UID_PROCESS_STATE_CHANGED, {1 /* uid*/});
1832     *links->mutable_fields_in_condition() = CreateRepeatedDimensions(
1833             util::TEST_ATOM_REPORTED, {9 /* repeated uid*/}, {Position::FIRST});
1834 
1835     // Initialize StatsLogProcessor.
1836     ConfigKey cfgKey(2000, 921);
1837     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1838     const uint64_t bucketSizeNs =
1839             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
1840     const uint64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
1841     sp<StatsLogProcessor> processor =
1842             CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1843 
1844     vector<int> intArray1 = {1, 2};
1845     vector<int> intArray2 = {2, 1};
1846     vector<int> enumArrayOn = {TestAtomReported::ON, TestAtomReported::OFF};
1847     vector<int> enumArrayOff = {TestAtomReported::OFF, TestAtomReported::ON};
1848 
1849     std::vector<std::unique_ptr<LogEvent>> events;
1850     // Set condition to true for uid 1.
1851     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1852             bucketStartTimeNs + 20 * NS_PER_SEC, intArray1, {}, {}, {}, {}, 0, enumArrayOff));
1853 
1854     // Uid 1 process state changed.
1855     events.push_back(CreateUidProcessStateChangedEvent(
1856             bucketStartTimeNs + 40 * NS_PER_SEC, 1 /*uid*/,
1857             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
1858     // Uid 2 process state changed. Should not be counted.
1859     events.push_back(CreateUidProcessStateChangedEvent(
1860             bucketStartTimeNs + 60 * NS_PER_SEC, 2 /*uid*/,
1861             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
1862 
1863     // Set condition to true for uid 2.
1864     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1865             bucketStartTimeNs + 80 * NS_PER_SEC, intArray2, {}, {}, {}, {}, 0, enumArrayOff));
1866     // Uid 1 process state changed.
1867     events.push_back(CreateUidProcessStateChangedEvent(
1868             bucketStartTimeNs + 100 * NS_PER_SEC, 1 /*uid*/,
1869             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
1870     // Uid 2 process state changed.
1871     events.push_back(CreateUidProcessStateChangedEvent(
1872             bucketStartTimeNs + 120 * NS_PER_SEC, 2 /*uid*/,
1873             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
1874 
1875     // Bucket 2
1876     // Set condition to false for uid 1.
1877     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(
1878             bucket2StartTimeNs + 20 * NS_PER_SEC, intArray1, {}, {}, {}, {}, 0, enumArrayOn));
1879     // Uid 1 process state changed. Should not be counted.
1880     events.push_back(CreateUidProcessStateChangedEvent(
1881             bucket2StartTimeNs + 40 * NS_PER_SEC, 1 /*uid*/,
1882             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
1883     // Uid 2 process state changed.
1884     events.push_back(CreateUidProcessStateChangedEvent(
1885             bucket2StartTimeNs + 60 * NS_PER_SEC, 2 /*uid*/,
1886             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));
1887 
1888     // Send log events to StatsLogProcessor.
1889     for (auto& event : events) {
1890         processor->OnLogEvent(event.get());
1891     }
1892 
1893     // Check dump report.
1894     vector<uint8_t> buffer;
1895     ConfigMetricsReportList reports;
1896     processor->onDumpReport(cfgKey, bucket2StartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
1897                             FAST, &buffer);
1898     ASSERT_GT(buffer.size(), 0);
1899     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1900     backfillDimensionPath(&reports);
1901     backfillStringInReport(&reports);
1902     backfillStartEndTimestamp(&reports);
1903 
1904     ASSERT_EQ(1, reports.reports_size());
1905     ASSERT_EQ(1, reports.reports(0).metrics_size());
1906     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
1907     StatsLogReport::CountMetricDataWrapper countMetrics;
1908     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
1909     ASSERT_EQ(2, countMetrics.data_size());
1910 
1911     CountMetricData data = countMetrics.data(0);
1912     ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
1913     EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value(0).field());
1914     EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
1915     ASSERT_EQ(1, data.bucket_info_size());
1916     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1917                         2);
1918 
1919     data = countMetrics.data(1);
1920     ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
1921     EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value(0).field());
1922     EXPECT_EQ(2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
1923     ASSERT_EQ(2, data.bucket_info_size());
1924     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
1925                         1);
1926     ValidateCountBucket(data.bucket_info(1), bucket2StartTimeNs, bucket2StartTimeNs + bucketSizeNs,
1927                         1);
1928 }
1929 
TEST(CountMetricE2eTest,TestDimensionalSampling)1930 TEST(CountMetricE2eTest, TestDimensionalSampling) {
1931     ShardOffsetProvider::getInstance().setShardOffset(5);
1932 
1933     // Initialize config.
1934     StatsdConfig config;
1935 
1936     AtomMatcher appCrashMatcher =
1937             CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED);
1938     *config.add_atom_matcher() = appCrashMatcher;
1939 
1940     CountMetric sampledCountMetric =
1941             createCountMetric("CountSampledAppCrashesPerUid", appCrashMatcher.id(), nullopt, {});
1942     *sampledCountMetric.mutable_dimensions_in_what() =
1943             CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
1944     *sampledCountMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
1945             CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
1946     sampledCountMetric.mutable_dimensional_sampling_info()->set_shard_count(2);
1947     *config.add_count_metric() = sampledCountMetric;
1948 
1949     // Initialize StatsLogProcessor.
1950     const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1951     const uint64_t bucketSizeNs =
1952             TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
1953     int uid = 12345;
1954     int64_t cfgId = 98765;
1955     ConfigKey cfgKey(uid, cfgId);
1956 
1957     sp<StatsLogProcessor> processor = CreateStatsLogProcessor(
1958             bucketStartTimeNs, bucketStartTimeNs, config, cfgKey, nullptr, 0, new UidMap());
1959 
1960     int appUid1 = 1001;  // odd hash value
1961     int appUid2 = 1002;  // even hash value
1962     int appUid3 = 1003;  // odd hash value
1963     std::vector<std::unique_ptr<LogEvent>> events;
1964     events.push_back(
1965             CreateAppCrashOccurredEvent(bucketStartTimeNs + 20 * NS_PER_SEC, appUid1));  // 0:30
1966     events.push_back(
1967             CreateAppCrashOccurredEvent(bucketStartTimeNs + 40 * NS_PER_SEC, appUid2));  // 0:50
1968     events.push_back(
1969             CreateAppCrashOccurredEvent(bucketStartTimeNs + 60 * NS_PER_SEC, appUid3));  // 1:10
1970     events.push_back(
1971             CreateAppCrashOccurredEvent(bucketStartTimeNs + 80 * NS_PER_SEC, appUid1));  // 1:20
1972     events.push_back(
1973             CreateAppCrashOccurredEvent(bucketStartTimeNs + 90 * NS_PER_SEC, appUid2));  // 1:30
1974     events.push_back(
1975             CreateAppCrashOccurredEvent(bucketStartTimeNs + 100 * NS_PER_SEC, appUid3));  // 1:40
1976 
1977     // Send log events to StatsLogProcessor.
1978     for (auto& event : events) {
1979         processor->OnLogEvent(event.get());
1980     }
1981 
1982     // Check dump report.
1983     vector<uint8_t> buffer;
1984     ConfigMetricsReportList reports;
1985     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
1986                             FAST, &buffer);
1987     ASSERT_GT(buffer.size(), 0);
1988     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1989     backfillDimensionPath(&reports);
1990     backfillStringInReport(&reports);
1991     backfillStartEndTimestamp(&reports);
1992 
1993     ASSERT_EQ(1, reports.reports_size());
1994     ASSERT_EQ(1, reports.reports(0).metrics_size());
1995     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
1996     StatsLogReport::CountMetricDataWrapper countMetrics;
1997     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
1998     ASSERT_EQ(2, countMetrics.data_size());
1999 
2000     // Only Uid 1 and 3 are logged. (odd hash value) + (offset of 5) % (shard count of 2) = 0
2001     CountMetricData data = countMetrics.data(0);
2002     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, appUid1);
2003     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
2004                         2);
2005 
2006     data = countMetrics.data(1);
2007     ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, appUid3);
2008     ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
2009                         2);
2010 }
2011 
2012 }  // namespace statsd
2013 }  // namespace os
2014 }  // namespace android
2015 #else
2016 GTEST_LOG_(INFO) << "This test does nothing.\n";
2017 #endif
2018