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