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