• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <gtest/gtest.h>
16 
17 #include <vector>
18 
19 #include "src/StatsLogProcessor.h"
20 #include "src/state/StateTracker.h"
21 #include "src/stats_log_util.h"
22 #include "tests/statsd_test_util.h"
23 
24 namespace android {
25 namespace os {
26 namespace statsd {
27 
28 #ifdef __ANDROID__
29 
TEST(DurationMetricE2eTest,TestOneBucket)30 TEST(DurationMetricE2eTest, TestOneBucket) {
31     StatsdConfig config;
32     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
33 
34     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
35     auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
36     *config.add_atom_matcher() = screenOnMatcher;
37     *config.add_atom_matcher() = screenOffMatcher;
38 
39     auto durationPredicate = CreateScreenIsOnPredicate();
40     *config.add_predicate() = durationPredicate;
41 
42     int64_t metricId = 123456;
43     auto durationMetric = config.add_duration_metric();
44     durationMetric->set_id(metricId);
45     durationMetric->set_what(durationPredicate.id());
46     durationMetric->set_bucket(FIVE_MINUTES);
47     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
48 
49     const int64_t baseTimeNs = 0;                                   // 0:00
50     const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC;  // 0:01
51     const int64_t bucketSizeNs =
52             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
53 
54     int uid = 12345;
55     int64_t cfgId = 98765;
56     ConfigKey cfgKey(uid, cfgId);
57 
58     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
59 
60     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
61     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
62     EXPECT_TRUE(metricsManager->isConfigValid());
63     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
64     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
65     EXPECT_TRUE(metricsManager->isActive());
66     EXPECT_TRUE(metricProducer->mIsActive);
67 
68     std::unique_ptr<LogEvent> event;
69 
70     // Screen is off at start of bucket.
71     event = CreateScreenStateChangedEvent(configAddedTimeNs,
72                                           android::view::DISPLAY_STATE_OFF);  // 0:01
73     processor->OnLogEvent(event.get());
74 
75     // Turn screen on.
76     const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC;  // 0:11
77     event = CreateScreenStateChangedEvent(durationStartNs, android::view::DISPLAY_STATE_ON);
78     processor->OnLogEvent(event.get());
79 
80     // Turn off screen 30 seconds after turning on.
81     const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC;  // 0:41
82     event = CreateScreenStateChangedEvent(durationEndNs, android::view::DISPLAY_STATE_OFF);
83     processor->OnLogEvent(event.get());
84 
85     event = CreateScreenBrightnessChangedEvent(durationEndNs + 1 * NS_PER_SEC, 64);  // 0:42
86     processor->OnLogEvent(event.get());
87 
88     ConfigMetricsReportList reports;
89     vector<uint8_t> buffer;
90     processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
91                             ADB_DUMP, FAST, &buffer);  // 5:01
92     EXPECT_TRUE(buffer.size() > 0);
93     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
94     backfillDimensionPath(&reports);
95     backfillStartEndTimestamp(&reports);
96     ASSERT_EQ(1, reports.reports_size());
97     ASSERT_EQ(1, reports.reports(0).metrics_size());
98     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
99     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
100 
101     StatsLogReport::DurationMetricDataWrapper durationMetrics;
102     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
103                                     &durationMetrics);
104     ASSERT_EQ(1, durationMetrics.data_size());
105 
106     DurationMetricData data = durationMetrics.data(0);
107     ASSERT_EQ(1, data.bucket_info_size());
108     EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
109     EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
110     EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
111 }
112 
TEST(DurationMetricE2eTest,TestTwoBuckets)113 TEST(DurationMetricE2eTest, TestTwoBuckets) {
114     StatsdConfig config;
115     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
116 
117     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
118     auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
119     *config.add_atom_matcher() = screenOnMatcher;
120     *config.add_atom_matcher() = screenOffMatcher;
121 
122     auto durationPredicate = CreateScreenIsOnPredicate();
123     *config.add_predicate() = durationPredicate;
124 
125     int64_t metricId = 123456;
126     auto durationMetric = config.add_duration_metric();
127     durationMetric->set_id(metricId);
128     durationMetric->set_what(durationPredicate.id());
129     durationMetric->set_bucket(FIVE_MINUTES);
130     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
131 
132     const int64_t baseTimeNs = 0;                                   // 0:00
133     const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC;  // 0:01
134     const int64_t bucketSizeNs =
135             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
136 
137     int uid = 12345;
138     int64_t cfgId = 98765;
139     ConfigKey cfgKey(uid, cfgId);
140 
141     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
142 
143     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
144     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
145     EXPECT_TRUE(metricsManager->isConfigValid());
146     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
147     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
148     EXPECT_TRUE(metricsManager->isActive());
149     EXPECT_TRUE(metricProducer->mIsActive);
150 
151     std::unique_ptr<LogEvent> event;
152 
153     // Screen is off at start of bucket.
154     event = CreateScreenStateChangedEvent(configAddedTimeNs,
155                                           android::view::DISPLAY_STATE_OFF);  // 0:01
156     processor->OnLogEvent(event.get());
157 
158     // Turn screen on.
159     const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC;  // 0:11
160     event = CreateScreenStateChangedEvent(durationStartNs, android::view::DISPLAY_STATE_ON);
161     processor->OnLogEvent(event.get());
162 
163     // Turn off screen 30 seconds after turning on.
164     const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC;  // 0:41
165     event = CreateScreenStateChangedEvent(durationEndNs, android::view::DISPLAY_STATE_OFF);
166     processor->OnLogEvent(event.get());
167 
168     event = CreateScreenBrightnessChangedEvent(durationEndNs + 1 * NS_PER_SEC, 64);  // 0:42
169     processor->OnLogEvent(event.get());
170 
171     ConfigMetricsReportList reports;
172     vector<uint8_t> buffer;
173     processor->onDumpReport(cfgKey, configAddedTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC, false,
174                             true, ADB_DUMP, FAST, &buffer);  // 10:01
175     EXPECT_TRUE(buffer.size() > 0);
176     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
177     backfillDimensionPath(&reports);
178     backfillStartEndTimestamp(&reports);
179     ASSERT_EQ(1, reports.reports_size());
180     ASSERT_EQ(1, reports.reports(0).metrics_size());
181     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
182     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
183 
184     StatsLogReport::DurationMetricDataWrapper durationMetrics;
185     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
186                                     &durationMetrics);
187     ASSERT_EQ(1, durationMetrics.data_size());
188 
189     DurationMetricData data = durationMetrics.data(0);
190     ASSERT_EQ(1, data.bucket_info_size());
191 
192     auto bucketInfo = data.bucket_info(0);
193     EXPECT_EQ(0, bucketInfo.bucket_num());
194     EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
195     EXPECT_EQ(configAddedTimeNs, bucketInfo.start_bucket_elapsed_nanos());
196     EXPECT_EQ(baseTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
197 }
198 
TEST(DurationMetricE2eTest,TestWithActivation)199 TEST(DurationMetricE2eTest, TestWithActivation) {
200     StatsdConfig config;
201     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
202 
203     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
204     auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
205     auto crashMatcher = CreateProcessCrashAtomMatcher();
206     *config.add_atom_matcher() = screenOnMatcher;
207     *config.add_atom_matcher() = screenOffMatcher;
208     *config.add_atom_matcher() = crashMatcher;
209 
210     auto durationPredicate = CreateScreenIsOnPredicate();
211     *config.add_predicate() = durationPredicate;
212 
213     int64_t metricId = 123456;
214     auto durationMetric = config.add_duration_metric();
215     durationMetric->set_id(metricId);
216     durationMetric->set_what(durationPredicate.id());
217     durationMetric->set_bucket(FIVE_MINUTES);
218     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
219 
220     auto metric_activation1 = config.add_metric_activation();
221     metric_activation1->set_metric_id(metricId);
222     auto event_activation1 = metric_activation1->add_event_activation();
223     event_activation1->set_atom_matcher_id(crashMatcher.id());
224     event_activation1->set_ttl_seconds(30);  // 30 secs.
225 
226     const int64_t bucketStartTimeNs = 10000000000;
227     const int64_t bucketSizeNs =
228             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
229 
230     int uid = 12345;
231     int64_t cfgId = 98765;
232     ConfigKey cfgKey(uid, cfgId);
233 
234     sp<UidMap> m = new UidMap();
235     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
236     sp<AlarmMonitor> anomalyAlarmMonitor;
237     sp<AlarmMonitor> subscriberAlarmMonitor;
238     vector<int64_t> activeConfigsBroadcast;
239 
240     std::shared_ptr<MockLogEventFilter> mockLogEventFilter = std::make_shared<MockLogEventFilter>();
241     EXPECT_CALL(*mockLogEventFilter, setAtomIds(StatsLogProcessor::getDefaultAtomIdSet(), _))
242             .Times(1);
243 
244     int broadcastCount = 0;
245     StatsLogProcessor processor(
246             m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, bucketStartTimeNs,
247             [](const ConfigKey& key) { return true; },
248             [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
249                                                              const vector<int64_t>& activeConfigs) {
250                 broadcastCount++;
251                 EXPECT_EQ(broadcastUid, uid);
252                 activeConfigsBroadcast.clear();
253                 activeConfigsBroadcast.insert(activeConfigsBroadcast.end(), activeConfigs.begin(),
254                                               activeConfigs.end());
255                 return true;
256             },
257             [](const ConfigKey&, const string&, const vector<int64_t>&) {}, mockLogEventFilter);
258 
259     EXPECT_CALL(*mockLogEventFilter, setAtomIds(CreateAtomIdSetFromConfig(config), &processor))
260             .Times(1);
261 
262     processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);  // 0:00
263 
264     ASSERT_EQ(processor.mMetricsManagers.size(), 1u);
265     sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
266     EXPECT_TRUE(metricsManager->isConfigValid());
267     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
268     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
269     auto& eventActivationMap = metricProducer->mEventActivationMap;
270 
271     EXPECT_FALSE(metricsManager->isActive());
272     EXPECT_FALSE(metricProducer->mIsActive);
273     ASSERT_EQ(eventActivationMap.size(), 1u);
274     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
275     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
276     EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
277     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
278 
279     std::unique_ptr<LogEvent> event;
280 
281     // Turn screen off.
282     event = CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * NS_PER_SEC,
283                                           android::view::DISPLAY_STATE_OFF);  // 0:02
284     processor.OnLogEvent(event.get(), bucketStartTimeNs + 2 * NS_PER_SEC);
285 
286     // Turn screen on.
287     const int64_t durationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC;  // 0:05
288     event = CreateScreenStateChangedEvent(durationStartNs, android::view::DISPLAY_STATE_ON);
289     processor.OnLogEvent(event.get(), durationStartNs);
290 
291     // Activate metric.
292     const int64_t activationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC;  // 0:10
293     const int64_t activationEndNs =
294             activationStartNs + event_activation1->ttl_seconds() * NS_PER_SEC;  // 0:40
295     event = CreateAppCrashEvent(activationStartNs, 111);
296     processor.OnLogEvent(event.get(), activationStartNs);
297     EXPECT_TRUE(metricsManager->isActive());
298     EXPECT_TRUE(metricProducer->mIsActive);
299     EXPECT_EQ(broadcastCount, 1);
300     ASSERT_EQ(activeConfigsBroadcast.size(), 1);
301     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
302     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
303     EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
304     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
305 
306     // Expire activation.
307     const int64_t expirationNs = activationEndNs + 7 * NS_PER_SEC;
308     event = CreateScreenBrightnessChangedEvent(expirationNs, 64);  // 0:47
309     processor.OnLogEvent(event.get(), expirationNs);
310     EXPECT_FALSE(metricsManager->isActive());
311     EXPECT_FALSE(metricProducer->mIsActive);
312     EXPECT_EQ(broadcastCount, 2);
313     ASSERT_EQ(activeConfigsBroadcast.size(), 0);
314     ASSERT_EQ(eventActivationMap.size(), 1u);
315     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
316     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
317     EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
318     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
319 
320     // Turn off screen 10 seconds after activation expiration.
321     const int64_t durationEndNs = activationEndNs + 10 * NS_PER_SEC;  // 0:50
322     event = CreateScreenStateChangedEvent(durationEndNs, android::view::DISPLAY_STATE_OFF);
323     processor.OnLogEvent(event.get(), durationEndNs);
324 
325     // Turn screen on.
326     const int64_t duration2StartNs = durationEndNs + 5 * NS_PER_SEC;  // 0:55
327     event = CreateScreenStateChangedEvent(duration2StartNs, android::view::DISPLAY_STATE_ON);
328     processor.OnLogEvent(event.get(), duration2StartNs);
329 
330     // Turn off screen.
331     const int64_t duration2EndNs = duration2StartNs + 10 * NS_PER_SEC;  // 1:05
332     event = CreateScreenStateChangedEvent(duration2EndNs, android::view::DISPLAY_STATE_OFF);
333     processor.OnLogEvent(event.get(), duration2EndNs);
334 
335     // Activate metric.
336     const int64_t activation2StartNs = duration2EndNs + 5 * NS_PER_SEC;  // 1:10
337     const int64_t activation2EndNs =
338             activation2StartNs + event_activation1->ttl_seconds() * NS_PER_SEC;  // 1:40
339     event = CreateAppCrashEvent(activation2StartNs, 211);
340     processor.OnLogEvent(event.get(), activation2StartNs);
341     EXPECT_TRUE(metricsManager->isActive());
342     EXPECT_TRUE(metricProducer->mIsActive);
343     EXPECT_EQ(broadcastCount, 3);
344     ASSERT_EQ(activeConfigsBroadcast.size(), 1);
345     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
346     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
347     EXPECT_EQ(eventActivationMap[2]->start_ns, activation2StartNs);
348     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
349 
350     ConfigMetricsReportList reports;
351     vector<uint8_t> buffer;
352     processor.onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
353                            ADB_DUMP, FAST, &buffer);  // 5:01
354     EXPECT_TRUE(buffer.size() > 0);
355     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
356     backfillDimensionPath(&reports);
357     backfillStartEndTimestamp(&reports);
358     ASSERT_EQ(1, reports.reports_size());
359     ASSERT_EQ(1, reports.reports(0).metrics_size());
360     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
361     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
362 
363     StatsLogReport::DurationMetricDataWrapper durationMetrics;
364     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
365                                     &durationMetrics);
366     ASSERT_EQ(1, durationMetrics.data_size());
367 
368     DurationMetricData data = durationMetrics.data(0);
369     ASSERT_EQ(1, data.bucket_info_size());
370 
371     auto bucketInfo = data.bucket_info(0);
372     EXPECT_EQ(0, bucketInfo.bucket_num());
373     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
374     EXPECT_EQ(expirationNs, bucketInfo.end_bucket_elapsed_nanos());
375     EXPECT_EQ(expirationNs - durationStartNs, bucketInfo.duration_nanos());
376 }
377 
TEST(DurationMetricE2eTest,TestWithCondition)378 TEST(DurationMetricE2eTest, TestWithCondition) {
379     StatsdConfig config;
380     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
381     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
382     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
383     *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
384     *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
385 
386     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
387     *config.add_predicate() = holdingWakelockPredicate;
388 
389     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
390     *config.add_predicate() = isInBackgroundPredicate;
391 
392     auto durationMetric = config.add_duration_metric();
393     durationMetric->set_id(StringToId("WakelockDuration"));
394     durationMetric->set_what(holdingWakelockPredicate.id());
395     durationMetric->set_condition(isInBackgroundPredicate.id());
396     durationMetric->set_aggregation_type(DurationMetric::SUM);
397     durationMetric->set_bucket(FIVE_MINUTES);
398 
399     ConfigKey cfgKey;
400     uint64_t bucketStartTimeNs = 10000000000;
401     uint64_t bucketSizeNs =
402             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
403     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
404     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
405     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
406     EXPECT_TRUE(metricsManager->isConfigValid());
407     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
408     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
409     auto& eventActivationMap = metricProducer->mEventActivationMap;
410     EXPECT_TRUE(metricsManager->isActive());
411     EXPECT_TRUE(metricProducer->mIsActive);
412     EXPECT_TRUE(eventActivationMap.empty());
413 
414     int appUid = 123;
415     vector<int> attributionUids1 = {appUid};
416     vector<string> attributionTags1 = {"App1"};
417     int64_t conditionStartTime1Ns = bucketStartTimeNs + 22 * NS_PER_SEC;
418     int64_t conditionEndTimeNs = bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC;
419     int64_t conditionStartTime2Ns = bucketStartTimeNs + (4 * 60 + 20) * NS_PER_SEC;
420     int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
421 
422     std::vector<std::unique_ptr<LogEvent>> events;
423     events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 10 * NS_PER_SEC,
424                                                 attributionUids1, attributionTags1,
425                                                 "wl1"));                           // 0:10
426     events.push_back(CreateMoveToBackgroundEvent(conditionStartTime1Ns, appUid));  // 0:22
427     events.push_back(CreateMoveToForegroundEvent(conditionEndTimeNs,
428                                                  appUid));  // 3:15
429     events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 4 * 60 * NS_PER_SEC,
430                                                 attributionUids1, attributionTags1,
431                                                 "wl1"));                           // 4:00
432     events.push_back(CreateMoveToBackgroundEvent(conditionStartTime2Ns, appUid));  // 4:20
433 
434     // Bucket 2.
435     events.push_back(CreateAcquireWakelockEvent(bucket2StartTimeNs + 10 * NS_PER_SEC,
436                                                 attributionUids1, attributionTags1,
437                                                 "wl1"));  // 5:10
438     // Send log events to StatsLogProcessor.
439     for (auto& event : events) {
440         processor->OnLogEvent(event.get());
441     }
442 
443     vector<uint8_t> buffer;
444     ConfigMetricsReportList reports;
445     int64_t dumpReportTimeNs = bucket2StartTimeNs + 40 * NS_PER_SEC;
446     processor->onDumpReport(cfgKey, dumpReportTimeNs, true, true, ADB_DUMP, FAST, &buffer);  // 5:40
447     ASSERT_GT(buffer.size(), 0);
448     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
449     backfillDimensionPath(&reports);
450     backfillStringInReport(&reports);
451     backfillStartEndTimestamp(&reports);
452 
453     ASSERT_EQ(1, reports.reports_size());
454     ASSERT_EQ(1, reports.reports(0).metrics_size());
455     StatsLogReport::DurationMetricDataWrapper durationMetrics;
456     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
457                                     &durationMetrics);
458     ASSERT_EQ(1, durationMetrics.data_size());
459 
460     // Validate bucket info.
461     ASSERT_EQ(2, durationMetrics.data(0).bucket_info_size());
462     ValidateDurationBucket(durationMetrics.data(0).bucket_info(0), bucketStartTimeNs,
463                            bucket2StartTimeNs, conditionEndTimeNs - conditionStartTime1Ns,
464                            (conditionEndTimeNs - conditionStartTime1Ns) +
465                                    (bucket2StartTimeNs - conditionStartTime2Ns));
466     ValidateDurationBucket(durationMetrics.data(0).bucket_info(1), bucket2StartTimeNs,
467                            dumpReportTimeNs, 30 * NS_PER_SEC,
468                            dumpReportTimeNs - bucket2StartTimeNs);
469 }
470 
TEST(DurationMetricE2eTest,TestWithSlicedCondition)471 TEST(DurationMetricE2eTest, TestWithSlicedCondition) {
472     StatsdConfig config;
473     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
474     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
475     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
476     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
477     *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
478     *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
479 
480     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
481     // The predicate is dimensioning by first attribution node by uid.
482     FieldMatcher dimensions = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED,
483                                                              {Position::FIRST});
484     *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
485     *config.add_predicate() = holdingWakelockPredicate;
486 
487     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
488     *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
489             CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
490     *config.add_predicate() = isInBackgroundPredicate;
491 
492     auto durationMetric = config.add_duration_metric();
493     durationMetric->set_id(StringToId("WakelockDuration"));
494     durationMetric->set_what(holdingWakelockPredicate.id());
495     durationMetric->set_condition(isInBackgroundPredicate.id());
496     durationMetric->set_aggregation_type(DurationMetric::SUM);
497     // The metric is dimensioning by first attribution node and only by uid.
498     *durationMetric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
499             util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
500     durationMetric->set_bucket(FIVE_MINUTES);
501 
502     // Links between wakelock state atom and condition of app is in background.
503     auto links = durationMetric->add_links();
504     links->set_condition(isInBackgroundPredicate.id());
505     *links->mutable_fields_in_what() =
506             CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
507     auto dimensionCondition = links->mutable_fields_in_condition();
508     dimensionCondition->set_field(util::ACTIVITY_FOREGROUND_STATE_CHANGED);
509     dimensionCondition->add_child()->set_field(1);  // uid field.
510 
511     ConfigKey cfgKey;
512     uint64_t bucketStartTimeNs = 10000000000;
513     uint64_t bucketSizeNs =
514             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
515     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
516     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
517     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
518     EXPECT_TRUE(metricsManager->isConfigValid());
519     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
520     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
521     auto& eventActivationMap = metricProducer->mEventActivationMap;
522     EXPECT_TRUE(metricsManager->isActive());
523     EXPECT_TRUE(metricProducer->mIsActive);
524     EXPECT_TRUE(eventActivationMap.empty());
525 
526     int appUid = 123;
527     std::vector<int> attributionUids1 = {appUid};
528     std::vector<string> attributionTags1 = {"App1"};
529 
530     auto event = CreateAcquireWakelockEvent(bucketStartTimeNs + 10 * NS_PER_SEC, attributionUids1,
531                                             attributionTags1, "wl1");  // 0:10
532     processor->OnLogEvent(event.get());
533 
534     event = CreateMoveToBackgroundEvent(bucketStartTimeNs + 22 * NS_PER_SEC, appUid);  // 0:22
535     processor->OnLogEvent(event.get());
536 
537     event = CreateReleaseWakelockEvent(bucketStartTimeNs + 60 * NS_PER_SEC, attributionUids1,
538                                        attributionTags1, "wl1");  // 1:00
539     processor->OnLogEvent(event.get());
540 
541     event = CreateMoveToForegroundEvent(bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC,
542                                         appUid);  // 3:15
543     processor->OnLogEvent(event.get());
544 
545     vector<uint8_t> buffer;
546     ConfigMetricsReportList reports;
547     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
548                             FAST, &buffer);
549     ASSERT_GT(buffer.size(), 0);
550     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
551     backfillDimensionPath(&reports);
552     backfillStringInReport(&reports);
553     backfillStartEndTimestamp(&reports);
554 
555     ASSERT_EQ(1, reports.reports_size());
556     ASSERT_EQ(1, reports.reports(0).metrics_size());
557     StatsLogReport::DurationMetricDataWrapper durationMetrics;
558     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
559                                     &durationMetrics);
560     ASSERT_EQ(1, durationMetrics.data_size());
561 
562     DurationMetricData data = durationMetrics.data(0);
563     // Validate dimension value.
564     ValidateAttributionUidDimension(data.dimensions_in_what(),
565                                     util::WAKELOCK_STATE_CHANGED, appUid);
566     // Validate bucket info.
567     ASSERT_EQ(1, data.bucket_info_size());
568 
569     auto bucketInfo = data.bucket_info(0);
570     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
571     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
572     EXPECT_EQ(38 * NS_PER_SEC, bucketInfo.duration_nanos());
573 }
574 
TEST(DurationMetricE2eTest,TestWithActivationAndSlicedCondition)575 TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition) {
576     StatsdConfig config;
577     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
578     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
579     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
580     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
581     *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
582     *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
583     *config.add_atom_matcher() = screenOnMatcher;
584 
585     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
586     // The predicate is dimensioning by first attribution node by uid.
587     FieldMatcher dimensions = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED,
588                                                              {Position::FIRST});
589     *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
590     *config.add_predicate() = holdingWakelockPredicate;
591 
592     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
593     *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
594             CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
595     *config.add_predicate() = isInBackgroundPredicate;
596 
597     auto durationMetric = config.add_duration_metric();
598     durationMetric->set_id(StringToId("WakelockDuration"));
599     durationMetric->set_what(holdingWakelockPredicate.id());
600     durationMetric->set_condition(isInBackgroundPredicate.id());
601     durationMetric->set_aggregation_type(DurationMetric::SUM);
602     // The metric is dimensioning by first attribution node and only by uid.
603     *durationMetric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
604             util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
605     durationMetric->set_bucket(FIVE_MINUTES);
606 
607     // Links between wakelock state atom and condition of app is in background.
608     auto links = durationMetric->add_links();
609     links->set_condition(isInBackgroundPredicate.id());
610     *links->mutable_fields_in_what() =
611             CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
612     auto dimensionCondition = links->mutable_fields_in_condition();
613     dimensionCondition->set_field(util::ACTIVITY_FOREGROUND_STATE_CHANGED);
614     dimensionCondition->add_child()->set_field(1);  // uid field.
615 
616     auto metric_activation1 = config.add_metric_activation();
617     metric_activation1->set_metric_id(durationMetric->id());
618     auto event_activation1 = metric_activation1->add_event_activation();
619     event_activation1->set_atom_matcher_id(screenOnMatcher.id());
620     event_activation1->set_ttl_seconds(60 * 2);  // 2 minutes.
621 
622     ConfigKey cfgKey;
623     uint64_t bucketStartTimeNs = 10000000000;
624     uint64_t bucketSizeNs =
625             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
626     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
627     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
628     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
629     EXPECT_TRUE(metricsManager->isConfigValid());
630     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
631     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
632     auto& eventActivationMap = metricProducer->mEventActivationMap;
633     EXPECT_FALSE(metricsManager->isActive());
634     EXPECT_FALSE(metricProducer->mIsActive);
635     ASSERT_EQ(eventActivationMap.size(), 1u);
636     EXPECT_TRUE(eventActivationMap.find(4) != eventActivationMap.end());
637     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
638     EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
639     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
640 
641     int appUid = 123;
642     std::vector<int> attributionUids1 = {appUid};
643     std::vector<string> attributionTags1 = {"App1"};
644 
645     auto event = CreateAcquireWakelockEvent(bucketStartTimeNs + 10 * NS_PER_SEC, attributionUids1,
646                                             attributionTags1, "wl1");  // 0:10
647     processor->OnLogEvent(event.get());
648     EXPECT_FALSE(metricsManager->isActive());
649     EXPECT_FALSE(metricProducer->mIsActive);
650     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
651     EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
652     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
653 
654     event = CreateMoveToBackgroundEvent(bucketStartTimeNs + 22 * NS_PER_SEC, appUid);  // 0:22
655     processor->OnLogEvent(event.get());
656     EXPECT_FALSE(metricsManager->isActive());
657     EXPECT_FALSE(metricProducer->mIsActive);
658     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
659     EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
660     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
661 
662     const int64_t durationStartNs = bucketStartTimeNs + 30 * NS_PER_SEC;  // 0:30
663     event = CreateScreenStateChangedEvent(durationStartNs, android::view::DISPLAY_STATE_ON);
664     processor->OnLogEvent(event.get());
665     EXPECT_TRUE(metricsManager->isActive());
666     EXPECT_TRUE(metricProducer->mIsActive);
667     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
668     EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
669     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
670 
671     const int64_t durationEndNs =
672             durationStartNs + (event_activation1->ttl_seconds() + 30) * NS_PER_SEC;  // 3:00
673     event = CreateAppCrashEvent(durationEndNs, 333);
674     processor->OnLogEvent(event.get());
675     EXPECT_FALSE(metricsManager->isActive());
676     EXPECT_FALSE(metricProducer->mIsActive);
677     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
678     EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
679     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
680 
681     event = CreateMoveToForegroundEvent(bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC,
682                                         appUid);  // 3:15
683     processor->OnLogEvent(event.get());
684 
685     event = CreateReleaseWakelockEvent(bucketStartTimeNs + (4 * 60 + 17) * NS_PER_SEC,
686                                        attributionUids1, attributionTags1, "wl1");  // 4:17
687     processor->OnLogEvent(event.get());
688 
689     event = CreateMoveToBackgroundEvent(bucketStartTimeNs + (4 * 60 + 20) * NS_PER_SEC,
690                                         appUid);  // 4:20
691     processor->OnLogEvent(event.get());
692 
693     event = CreateAcquireWakelockEvent(bucketStartTimeNs + (4 * 60 + 25) * NS_PER_SEC,
694                                        attributionUids1, attributionTags1, "wl1");  // 4:25
695     processor->OnLogEvent(event.get());
696 
697     const int64_t duration2StartNs = bucketStartTimeNs + (4 * 60 + 30) * NS_PER_SEC;  // 4:30
698     event = CreateScreenStateChangedEvent(duration2StartNs, android::view::DISPLAY_STATE_ON);
699     processor->OnLogEvent(event.get());
700     EXPECT_TRUE(metricsManager->isActive());
701     EXPECT_TRUE(metricProducer->mIsActive);
702     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
703     EXPECT_EQ(eventActivationMap[4]->start_ns, duration2StartNs);
704     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
705 
706     vector<uint8_t> buffer;
707     ConfigMetricsReportList reports;
708     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
709                             FAST, &buffer);
710     ASSERT_GT(buffer.size(), 0);
711     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
712     backfillDimensionPath(&reports);
713     backfillStringInReport(&reports);
714     backfillStartEndTimestamp(&reports);
715 
716     ASSERT_EQ(1, reports.reports_size());
717     ASSERT_EQ(1, reports.reports(0).metrics_size());
718     StatsLogReport::DurationMetricDataWrapper durationMetrics;
719     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
720                                     &durationMetrics);
721     ASSERT_EQ(1, durationMetrics.data_size());
722 
723     DurationMetricData data = durationMetrics.data(0);
724     // Validate dimension value.
725     ValidateAttributionUidDimension(data.dimensions_in_what(),
726                                     util::WAKELOCK_STATE_CHANGED, appUid);
727     // Validate bucket info.
728     ASSERT_EQ(2, data.bucket_info_size());
729 
730     auto bucketInfo = data.bucket_info(0);
731     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
732     EXPECT_EQ(durationEndNs, bucketInfo.end_bucket_elapsed_nanos());
733     EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
734 
735     bucketInfo = data.bucket_info(1);
736     EXPECT_EQ(durationEndNs, bucketInfo.start_bucket_elapsed_nanos());
737     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
738     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - duration2StartNs, bucketInfo.duration_nanos());
739 }
740 
TEST(DurationMetricE2eTest,TestWithSlicedState)741 TEST(DurationMetricE2eTest, TestWithSlicedState) {
742     // Initialize config.
743     StatsdConfig config;
744     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
745 
746     *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher();
747     *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher();
748 
749     auto batterySaverModePredicate = CreateBatterySaverModePredicate();
750     *config.add_predicate() = batterySaverModePredicate;
751 
752     auto screenState = CreateScreenState();
753     *config.add_state() = screenState;
754 
755     // Create duration metric that slices by screen state.
756     auto durationMetric = config.add_duration_metric();
757     durationMetric->set_id(StringToId("DurationBatterySaverModeSliceScreen"));
758     durationMetric->set_what(batterySaverModePredicate.id());
759     durationMetric->add_slice_by_state(screenState.id());
760     durationMetric->set_aggregation_type(DurationMetric::SUM);
761     durationMetric->set_bucket(FIVE_MINUTES);
762 
763     // Initialize StatsLogProcessor.
764     int uid = 12345;
765     int64_t cfgId = 98765;
766     ConfigKey cfgKey(uid, cfgId);
767     uint64_t bucketStartTimeNs = 10000000000;  // 0:10
768     uint64_t bucketSizeNs =
769             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
770     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
771 
772     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
773     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
774     EXPECT_TRUE(metricsManager->isConfigValid());
775     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
776     EXPECT_TRUE(metricsManager->isActive());
777     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
778     EXPECT_TRUE(metricProducer->mIsActive);
779     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
780     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
781     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
782 
783     // Check that StateTrackers were initialized correctly.
784     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
785     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
786 
787     /*
788                bucket #1                      bucket #2
789     |     1     2     3     4     5     6     7     8     9     10 (minutes)
790     |-----------------------------|-----------------------------|--
791         ON              OFF     ON                                  (BatterySaverMode)
792       |          |                   |                              (ScreenIsOnEvent)
793            |                  |                                     (ScreenIsOffEvent)
794               |                                                     (ScreenDozeEvent)
795     */
796     // Initialize log events.
797     std::vector<std::unique_ptr<LogEvent>> events;
798     events.push_back(CreateScreenStateChangedEvent(
799             bucketStartTimeNs + 10 * NS_PER_SEC,
800             android::view::DisplayStateEnum::DISPLAY_STATE_ON));                       // 0:20
801     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
802     events.push_back(CreateScreenStateChangedEvent(
803             bucketStartTimeNs + 50 * NS_PER_SEC,
804             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 1:00
805     events.push_back(CreateScreenStateChangedEvent(
806             bucketStartTimeNs + 80 * NS_PER_SEC,
807             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 1:30
808     events.push_back(CreateScreenStateChangedEvent(
809             bucketStartTimeNs + 120 * NS_PER_SEC,
810             android::view::DisplayStateEnum::DISPLAY_STATE_ON));                         // 2:10
811     events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
812     events.push_back(CreateScreenStateChangedEvent(
813             bucketStartTimeNs + 250 * NS_PER_SEC,
814             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));                       // 4:20
815     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
816 
817     // Bucket boundary.
818     events.push_back(CreateScreenStateChangedEvent(
819             bucketStartTimeNs + 310 * NS_PER_SEC,
820             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 5:20
821 
822     // Send log events to StatsLogProcessor.
823     for (auto& event : events) {
824         processor->OnLogEvent(event.get());
825     }
826 
827     // Check dump report.
828     vector<uint8_t> buffer;
829     ConfigMetricsReportList reports;
830     processor->onDumpReport(cfgKey, bucketStartTimeNs + 360 * NS_PER_SEC,
831                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
832                             &buffer);  // 6:10
833     ASSERT_GT(buffer.size(), 0);
834     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
835     backfillDimensionPath(&reports);
836     backfillStringInReport(&reports);
837     backfillStartEndTimestamp(&reports);
838 
839     ASSERT_EQ(1, reports.reports_size());
840     ASSERT_EQ(1, reports.reports(0).metrics_size());
841     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
842     StatsLogReport::DurationMetricDataWrapper durationMetrics;
843     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
844                                     &durationMetrics);
845     ASSERT_EQ(3, durationMetrics.data_size());
846 
847     DurationMetricData data = durationMetrics.data(0);
848     ASSERT_EQ(1, data.slice_by_state_size());
849     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
850     EXPECT_TRUE(data.slice_by_state(0).has_value());
851     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
852     ASSERT_EQ(2, data.bucket_info_size());
853     EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
854     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
855     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
856     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
857     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
858     EXPECT_EQ(370 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
859 
860     data = durationMetrics.data(1);
861     ASSERT_EQ(1, data.slice_by_state_size());
862     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
863     EXPECT_TRUE(data.slice_by_state(0).has_value());
864     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
865     ASSERT_EQ(2, data.bucket_info_size());
866     EXPECT_EQ(110 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
867     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
868     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
869     EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
870     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
871     EXPECT_EQ(370 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
872 
873     data = durationMetrics.data(2);
874     ASSERT_EQ(1, data.slice_by_state_size());
875     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
876     EXPECT_TRUE(data.slice_by_state(0).has_value());
877     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE, data.slice_by_state(0).value());
878     ASSERT_EQ(1, data.bucket_info_size());
879     EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
880     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
881     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
882 }
883 
TEST(DurationMetricE2eTest,TestWithConditionAndSlicedState)884 TEST(DurationMetricE2eTest, TestWithConditionAndSlicedState) {
885     // Initialize config.
886     StatsdConfig config;
887     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
888 
889     *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher();
890     *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher();
891     *config.add_atom_matcher() = CreateBatteryStateNoneMatcher();
892     *config.add_atom_matcher() = CreateBatteryStateUsbMatcher();
893 
894     auto batterySaverModePredicate = CreateBatterySaverModePredicate();
895     *config.add_predicate() = batterySaverModePredicate;
896 
897     auto deviceUnpluggedPredicate = CreateDeviceUnpluggedPredicate();
898     *config.add_predicate() = deviceUnpluggedPredicate;
899 
900     auto screenState = CreateScreenState();
901     *config.add_state() = screenState;
902 
903     // Create duration metric that has a condition and slices by screen state.
904     auto durationMetric = config.add_duration_metric();
905     durationMetric->set_id(StringToId("DurationBatterySaverModeOnBatterySliceScreen"));
906     durationMetric->set_what(batterySaverModePredicate.id());
907     durationMetric->set_condition(deviceUnpluggedPredicate.id());
908     durationMetric->add_slice_by_state(screenState.id());
909     durationMetric->set_aggregation_type(DurationMetric::SUM);
910     durationMetric->set_bucket(FIVE_MINUTES);
911 
912     // Initialize StatsLogProcessor.
913     int uid = 12345;
914     int64_t cfgId = 98765;
915     ConfigKey cfgKey(uid, cfgId);
916     uint64_t bucketStartTimeNs = 10000000000;  // 0:10
917     uint64_t bucketSizeNs =
918             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
919     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
920 
921     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
922     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
923     EXPECT_TRUE(metricsManager->isConfigValid());
924     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
925     EXPECT_TRUE(metricsManager->isActive());
926     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
927     EXPECT_TRUE(metricProducer->mIsActive);
928     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
929     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
930     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
931 
932     // Check that StateTrackers were initialized correctly.
933     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
934     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
935 
936     /*
937                bucket #1                      bucket #2
938     |       1       2       3       4       5     6     7     8  (minutes)
939     |---------------------------------------|------------------
940              ON                          OFF    ON             (BatterySaverMode)
941                   T            F    T                          (DeviceUnpluggedPredicate)
942          |              |              |                       (ScreenIsOnEvent)
943                 |           |                       |          (ScreenIsOffEvent)
944                                 |                              (ScreenDozeEvent)
945     */
946     // Initialize log events.
947     std::vector<std::unique_ptr<LogEvent>> events;
948     events.push_back(CreateScreenStateChangedEvent(
949             bucketStartTimeNs + 20 * NS_PER_SEC,
950             android::view::DisplayStateEnum::DISPLAY_STATE_ON));                       // 0:30
951     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 60 * NS_PER_SEC));  // 1:10
952     events.push_back(CreateScreenStateChangedEvent(
953             bucketStartTimeNs + 80 * NS_PER_SEC,
954             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 1:30
955     events.push_back(
956             CreateBatteryStateChangedEvent(bucketStartTimeNs + 110 * NS_PER_SEC,
957                                            BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE));  // 2:00
958     events.push_back(CreateScreenStateChangedEvent(
959             bucketStartTimeNs + 145 * NS_PER_SEC,
960             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 2:35
961     events.push_back(CreateScreenStateChangedEvent(
962             bucketStartTimeNs + 170 * NS_PER_SEC,
963             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 3:00
964     events.push_back(
965             CreateBatteryStateChangedEvent(bucketStartTimeNs + 180 * NS_PER_SEC,
966                                            BatteryPluggedStateEnum::BATTERY_PLUGGED_USB));  // 3:10
967     events.push_back(CreateScreenStateChangedEvent(
968             bucketStartTimeNs + 200 * NS_PER_SEC,
969             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 3:30
970     events.push_back(
971             CreateBatteryStateChangedEvent(bucketStartTimeNs + 230 * NS_PER_SEC,
972                                            BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE));  // 4:00
973     events.push_back(CreateScreenStateChangedEvent(
974             bucketStartTimeNs + 260 * NS_PER_SEC,
975             android::view::DisplayStateEnum::DISPLAY_STATE_ON));                         // 4:30
976     events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
977 
978     // Bucket boundary.
979     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 320 * NS_PER_SEC));  // 5:30
980     events.push_back(CreateScreenStateChangedEvent(
981             bucketStartTimeNs + 380 * NS_PER_SEC,
982             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 6:30
983 
984     // Send log events to StatsLogProcessor.
985     for (auto& event : events) {
986         processor->OnLogEvent(event.get());
987     }
988 
989     // Check dump report.
990     vector<uint8_t> buffer;
991     ConfigMetricsReportList reports;
992     processor->onDumpReport(cfgKey, bucketStartTimeNs + 410 * NS_PER_SEC,
993                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
994                             &buffer);
995     ASSERT_GT(buffer.size(), 0);
996     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
997     backfillDimensionPath(&reports);
998     backfillStringInReport(&reports);
999     backfillStartEndTimestamp(&reports);
1000 
1001     ASSERT_EQ(1, reports.reports_size());
1002     ASSERT_EQ(1, reports.reports(0).metrics_size());
1003     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
1004     StatsLogReport::DurationMetricDataWrapper durationMetrics;
1005     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1006                                     &durationMetrics);
1007     ASSERT_EQ(3, durationMetrics.data_size());
1008 
1009     DurationMetricData data = durationMetrics.data(0);
1010     ASSERT_EQ(1, data.slice_by_state_size());
1011     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1012     EXPECT_TRUE(data.slice_by_state(0).has_value());
1013     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
1014     ASSERT_EQ(2, data.bucket_info_size());
1015     EXPECT_EQ(45 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1016     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1017     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1018     EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1019     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1020     EXPECT_EQ(420 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1021 
1022     data = durationMetrics.data(1);
1023     ASSERT_EQ(1, data.slice_by_state_size());
1024     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1025     EXPECT_TRUE(data.slice_by_state(0).has_value());
1026     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
1027     ASSERT_EQ(2, data.bucket_info_size());
1028     EXPECT_EQ(45 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1029     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1030     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1031     EXPECT_EQ(60 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1032     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1033     EXPECT_EQ(420 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1034 
1035     data = durationMetrics.data(2);
1036     ASSERT_EQ(1, data.slice_by_state_size());
1037     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1038     EXPECT_TRUE(data.slice_by_state(0).has_value());
1039     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE, data.slice_by_state(0).value());
1040     ASSERT_EQ(1, data.bucket_info_size());
1041     EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1042     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1043     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1044 }
1045 
TEST(DurationMetricE2eTest,TestWithSlicedStateMapped)1046 TEST(DurationMetricE2eTest, TestWithSlicedStateMapped) {
1047     // Initialize config.
1048     StatsdConfig config;
1049     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
1050 
1051     *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher();
1052     *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher();
1053 
1054     auto batterySaverModePredicate = CreateBatterySaverModePredicate();
1055     *config.add_predicate() = batterySaverModePredicate;
1056 
1057     int64_t screenOnId = 4444;
1058     int64_t screenOffId = 9876;
1059     auto screenStateWithMap = CreateScreenStateWithOnOffMap(screenOnId, screenOffId);
1060     *config.add_state() = screenStateWithMap;
1061 
1062     // Create duration metric that slices by mapped screen state.
1063     auto durationMetric = config.add_duration_metric();
1064     durationMetric->set_id(StringToId("DurationBatterySaverModeSliceScreenMapped"));
1065     durationMetric->set_what(batterySaverModePredicate.id());
1066     durationMetric->add_slice_by_state(screenStateWithMap.id());
1067     durationMetric->set_aggregation_type(DurationMetric::SUM);
1068     durationMetric->set_bucket(FIVE_MINUTES);
1069 
1070     // Initialize StatsLogProcessor.
1071     int uid = 12345;
1072     int64_t cfgId = 98765;
1073     ConfigKey cfgKey(uid, cfgId);
1074     uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1075     uint64_t bucketSizeNs =
1076             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
1077     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1078 
1079     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
1080     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
1081     EXPECT_TRUE(metricsManager->isConfigValid());
1082     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
1083     EXPECT_TRUE(metricsManager->isActive());
1084     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
1085     EXPECT_TRUE(metricProducer->mIsActive);
1086     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
1087     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
1088     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 1);
1089 
1090     // Check that StateTrackers were initialized correctly.
1091     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
1092     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
1093 
1094     /*
1095                bucket #1                      bucket #2
1096     |     1     2     3     4     5     6     7     8     9     10 (minutes)
1097     |-----------------------------|-----------------------------|--
1098         ON              OFF     ON                                  (BatterySaverMode)
1099      ---------------------------------------------------------SCREEN_OFF events
1100            |                  |                                  (ScreenStateOffEvent = 1)
1101               |                                                  (ScreenStateDozeEvent = 3)
1102                                                 |                (ScreenStateDozeSuspendEvent = 4)
1103      ---------------------------------------------------------SCREEN_ON events
1104       |          |                   |                           (ScreenStateOnEvent = 2)
1105                       |                                          (ScreenStateVrEvent = 5)
1106                                             |                    (ScreenStateOnSuspendEvent = 6)
1107     */
1108     // Initialize log events.
1109     std::vector<std::unique_ptr<LogEvent>> events;
1110     events.push_back(CreateScreenStateChangedEvent(
1111             bucketStartTimeNs + 10 * NS_PER_SEC,
1112             android::view::DisplayStateEnum::DISPLAY_STATE_ON));                       // 0:20
1113     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
1114     events.push_back(CreateScreenStateChangedEvent(
1115             bucketStartTimeNs + 70 * NS_PER_SEC,
1116             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 1:20
1117     events.push_back(CreateScreenStateChangedEvent(
1118             bucketStartTimeNs + 100 * NS_PER_SEC,
1119             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 1:50
1120     events.push_back(CreateScreenStateChangedEvent(
1121             bucketStartTimeNs + 120 * NS_PER_SEC,
1122             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 2:10
1123     events.push_back(CreateScreenStateChangedEvent(
1124             bucketStartTimeNs + 170 * NS_PER_SEC,
1125             android::view::DisplayStateEnum::DISPLAY_STATE_VR));                         // 3:00
1126     events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
1127     events.push_back(CreateScreenStateChangedEvent(
1128             bucketStartTimeNs + 250 * NS_PER_SEC,
1129             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));                       // 4:20
1130     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
1131 
1132     // Bucket boundary 5:10.
1133     events.push_back(CreateScreenStateChangedEvent(
1134             bucketStartTimeNs + 320 * NS_PER_SEC,
1135             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 5:30
1136     events.push_back(CreateScreenStateChangedEvent(
1137             bucketStartTimeNs + 390 * NS_PER_SEC,
1138             android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND));  // 6:40
1139     events.push_back(CreateScreenStateChangedEvent(
1140             bucketStartTimeNs + 430 * NS_PER_SEC,
1141             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE_SUSPEND));  // 7:20
1142     // Send log events to StatsLogProcessor.
1143     for (auto& event : events) {
1144         processor->OnLogEvent(event.get());
1145     }
1146 
1147     // Check dump report.
1148     vector<uint8_t> buffer;
1149     ConfigMetricsReportList reports;
1150     processor->onDumpReport(cfgKey, bucketStartTimeNs + 490 * NS_PER_SEC,
1151                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
1152                             &buffer);
1153     ASSERT_GT(buffer.size(), 0);
1154     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1155     backfillDimensionPath(&reports);
1156     backfillStringInReport(&reports);
1157     backfillStartEndTimestamp(&reports);
1158 
1159     ASSERT_EQ(1, reports.reports_size());
1160     ASSERT_EQ(1, reports.reports(0).metrics_size());
1161     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
1162     StatsLogReport::DurationMetricDataWrapper durationMetrics;
1163     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1164                                     &durationMetrics);
1165     ASSERT_EQ(2, durationMetrics.data_size());
1166 
1167     DurationMetricData data = durationMetrics.data(0);
1168     ASSERT_EQ(1, data.slice_by_state_size());
1169     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1170     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
1171     EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
1172     ASSERT_EQ(2, data.bucket_info_size());
1173     EXPECT_EQ(130 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1174     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1175     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1176     EXPECT_EQ(110 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1177     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1178     EXPECT_EQ(500 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1179 
1180     data = durationMetrics.data(1);
1181     ASSERT_EQ(1, data.slice_by_state_size());
1182     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1183     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
1184     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
1185     ASSERT_EQ(2, data.bucket_info_size());
1186     EXPECT_EQ(70 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1187     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1188     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1189     EXPECT_EQ(80 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1190     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1191     EXPECT_EQ(500 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1192 }
1193 
TEST(DurationMetricE2eTest,TestSlicedStatePrimaryFieldsNotSubsetDimInWhat)1194 TEST(DurationMetricE2eTest, TestSlicedStatePrimaryFieldsNotSubsetDimInWhat) {
1195     // Initialize config.
1196     StatsdConfig config;
1197     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
1198 
1199     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
1200     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
1201 
1202     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
1203     *config.add_predicate() = holdingWakelockPredicate;
1204 
1205     auto uidProcessState = CreateUidProcessState();
1206     *config.add_state() = uidProcessState;
1207 
1208     // Create duration metric that slices by uid process state.
1209     auto durationMetric = config.add_duration_metric();
1210     durationMetric->set_id(StringToId("DurationHoldingWakelockSliceUidProcessState"));
1211     durationMetric->set_what(holdingWakelockPredicate.id());
1212     durationMetric->add_slice_by_state(uidProcessState.id());
1213     durationMetric->set_aggregation_type(DurationMetric::SUM);
1214     durationMetric->set_bucket(FIVE_MINUTES);
1215 
1216     // The state has only one primary field (uid).
1217     auto stateLink = durationMetric->add_state_link();
1218     stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
1219     auto fieldsInWhat = stateLink->mutable_fields_in_what();
1220     *fieldsInWhat = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
1221     auto fieldsInState = stateLink->mutable_fields_in_state();
1222     *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
1223 
1224     // Initialize StatsLogProcessor.
1225     int uid = 12345;
1226     int64_t cfgId = 98765;
1227     ConfigKey cfgKey(uid, cfgId);
1228     uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1229     uint64_t bucketSizeNs =
1230             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
1231     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1232 
1233     // This config is rejected because the dimension in what fields are not a superset of the sliced
1234     // state primary fields.
1235     ASSERT_EQ(processor->mMetricsManagers.size(), 0);
1236 }
1237 
TEST(DurationMetricE2eTest,TestWithSlicedStatePrimaryFieldsSubset)1238 TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset) {
1239     // Initialize config.
1240     StatsdConfig config;
1241     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
1242 
1243     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
1244     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
1245 
1246     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
1247     *(holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions()) =
1248             CreateAttributionUidAndOtherDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST},
1249                                                    {3 /* tag */});
1250     *config.add_predicate() = holdingWakelockPredicate;
1251 
1252     auto uidProcessState = CreateUidProcessState();
1253     *config.add_state() = uidProcessState;
1254 
1255     // Create duration metric that slices by uid process state.
1256     auto durationMetric = config.add_duration_metric();
1257     durationMetric->set_id(StringToId("DurationPartialWakelockPerTagUidSliceProcessState"));
1258     durationMetric->set_what(holdingWakelockPredicate.id());
1259     durationMetric->add_slice_by_state(uidProcessState.id());
1260     durationMetric->set_aggregation_type(DurationMetric::SUM);
1261     durationMetric->set_bucket(FIVE_MINUTES);
1262 
1263     // The metric is dimensioning by first uid of attribution node and tag.
1264     *durationMetric->mutable_dimensions_in_what() = CreateAttributionUidAndOtherDimensions(
1265             util::WAKELOCK_STATE_CHANGED, {Position::FIRST}, {3 /* tag */});
1266     // The state has only one primary field (uid).
1267     auto stateLink = durationMetric->add_state_link();
1268     stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
1269     auto fieldsInWhat = stateLink->mutable_fields_in_what();
1270     *fieldsInWhat = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
1271     auto fieldsInState = stateLink->mutable_fields_in_state();
1272     *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
1273 
1274     // Initialize StatsLogProcessor.
1275     int uid = 12345;
1276     int64_t cfgId = 98765;
1277     ConfigKey cfgKey(uid, cfgId);
1278     uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1279     uint64_t bucketSizeNs =
1280             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
1281     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1282 
1283     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
1284     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
1285     EXPECT_TRUE(metricsManager->isConfigValid());
1286     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
1287     EXPECT_TRUE(metricsManager->isActive());
1288     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
1289     EXPECT_TRUE(metricProducer->mIsActive);
1290     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
1291     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), UID_PROCESS_STATE_ATOM_ID);
1292     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
1293 
1294     // Check that StateTrackers were initialized correctly.
1295     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
1296     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
1297 
1298     // Initialize log events.
1299     int appUid1 = 1001;
1300     int appUid2 = 1002;
1301     std::vector<int> attributionUids1 = {appUid1};
1302     std::vector<string> attributionTags1 = {"App1"};
1303 
1304     std::vector<int> attributionUids2 = {appUid2};
1305     std::vector<string> attributionTags2 = {"App2"};
1306 
1307     std::vector<std::unique_ptr<LogEvent>> events;
1308     events.push_back(CreateUidProcessStateChangedEvent(
1309             bucketStartTimeNs + 10 * NS_PER_SEC, appUid1,
1310             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));  // 0:20
1311     events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 20 * NS_PER_SEC,
1312                                                 attributionUids1, attributionTags1,
1313                                                 "wakelock1"));  // 0:30
1314     events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 25 * NS_PER_SEC,
1315                                                 attributionUids1, attributionTags1,
1316                                                 "wakelock2"));  // 0:35
1317     events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 30 * NS_PER_SEC,
1318                                                 attributionUids2, attributionTags2,
1319                                                 "wakelock1"));  // 0:40
1320     events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 35 * NS_PER_SEC,
1321                                                 attributionUids2, attributionTags2,
1322                                                 "wakelock2"));  // 0:45
1323     events.push_back(CreateUidProcessStateChangedEvent(
1324             bucketStartTimeNs + 50 * NS_PER_SEC, appUid2,
1325             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND));  // 1:00
1326     events.push_back(CreateUidProcessStateChangedEvent(
1327             bucketStartTimeNs + 60 * NS_PER_SEC, appUid1,
1328             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND));  // 1:10
1329     events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 100 * NS_PER_SEC,
1330                                                 attributionUids2, attributionTags2,
1331                                                 "wakelock1"));  // 1:50
1332     events.push_back(CreateUidProcessStateChangedEvent(
1333             bucketStartTimeNs + 120 * NS_PER_SEC, appUid2,
1334             android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE));  // 2:10
1335     events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 200 * NS_PER_SEC,
1336                                                 attributionUids1, attributionTags1,
1337                                                 "wakelock2"));  // 3:30
1338 
1339     // Send log events to StatsLogProcessor.
1340     for (auto& event : events) {
1341         processor->OnLogEvent(event.get());
1342     }
1343 
1344     // Check dump report.
1345     vector<uint8_t> buffer;
1346     ConfigMetricsReportList reports;
1347     processor->onDumpReport(cfgKey, bucketStartTimeNs + 320 * NS_PER_SEC,
1348                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
1349                             &buffer);
1350     ASSERT_GT(buffer.size(), 0);
1351     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1352     backfillDimensionPath(&reports);
1353     backfillStringInReport(&reports);
1354     backfillStartEndTimestamp(&reports);
1355 
1356     ASSERT_EQ(1, reports.reports_size());
1357     ASSERT_EQ(1, reports.reports(0).metrics_size());
1358     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
1359     StatsLogReport::DurationMetricDataWrapper durationMetrics;
1360     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1361                                     &durationMetrics);
1362     ASSERT_EQ(9, durationMetrics.data_size());
1363 
1364     DurationMetricData data = durationMetrics.data(0);
1365     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
1366                                                   "wakelock1");
1367     ASSERT_EQ(1, data.slice_by_state_size());
1368     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1369     EXPECT_TRUE(data.slice_by_state(0).has_value());
1370     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
1371               data.slice_by_state(0).value());
1372     ASSERT_EQ(1, data.bucket_info_size());
1373     EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1374     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1375     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1376 
1377     data = durationMetrics.data(1);
1378     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
1379                                                   "wakelock1");
1380     ASSERT_EQ(1, data.slice_by_state_size());
1381     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1382     EXPECT_TRUE(data.slice_by_state(0).has_value());
1383     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1384               data.slice_by_state(0).value());
1385     ASSERT_EQ(2, data.bucket_info_size());
1386     EXPECT_EQ(240 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1387     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1388     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1389     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1390     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1391     EXPECT_EQ(330 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1392 
1393     data = durationMetrics.data(2);
1394     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
1395                                                   "wakelock2");
1396     ASSERT_EQ(1, data.slice_by_state_size());
1397     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1398     EXPECT_TRUE(data.slice_by_state(0).has_value());
1399     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
1400               data.slice_by_state(0).value());
1401     ASSERT_EQ(1, data.bucket_info_size());
1402     EXPECT_EQ(35 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1403     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1404     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1405 
1406     data = durationMetrics.data(3);
1407     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
1408                                                   "wakelock2");
1409     ASSERT_EQ(1, data.slice_by_state_size());
1410     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1411     EXPECT_TRUE(data.slice_by_state(0).has_value());
1412     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1413               data.slice_by_state(0).value());
1414     ASSERT_EQ(1, data.bucket_info_size());
1415     EXPECT_EQ(140 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1416     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1417     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1418 
1419     data = durationMetrics.data(4);
1420     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1421                                                   "wakelock1");
1422     ASSERT_EQ(1, data.slice_by_state_size());
1423     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1424     EXPECT_TRUE(data.slice_by_state(0).has_value());
1425     EXPECT_EQ(-1 /* StateTracker:: kStateUnknown */, data.slice_by_state(0).value());
1426     ASSERT_EQ(1, data.bucket_info_size());
1427     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1428     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1429     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1430 
1431     data = durationMetrics.data(5);
1432     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1433                                                   "wakelock1");
1434     ASSERT_EQ(1, data.slice_by_state_size());
1435     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1436     EXPECT_TRUE(data.slice_by_state(0).has_value());
1437     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1438               data.slice_by_state(0).value());
1439     ASSERT_EQ(1, data.bucket_info_size());
1440     EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1441     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1442     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1443 
1444     data = durationMetrics.data(6);
1445     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1446                                                   "wakelock2");
1447     ASSERT_EQ(1, data.slice_by_state_size());
1448     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1449     EXPECT_TRUE(data.slice_by_state(0).has_value());
1450     EXPECT_EQ(-1 /* StateTracker:: kStateUnknown */, data.slice_by_state(0).value());
1451     ASSERT_EQ(1, data.bucket_info_size());
1452     EXPECT_EQ(15 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1453     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1454     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1455 
1456     data = durationMetrics.data(7);
1457     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1458                                                   "wakelock2");
1459     ASSERT_EQ(1, data.slice_by_state_size());
1460     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1461     EXPECT_TRUE(data.slice_by_state(0).has_value());
1462     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
1463               data.slice_by_state(0).value());
1464     ASSERT_EQ(2, data.bucket_info_size());
1465     EXPECT_EQ(180 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1466     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1467     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1468     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1469     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1470     EXPECT_EQ(330 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1471 
1472     data = durationMetrics.data(8);
1473     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1474                                                   "wakelock2");
1475     ASSERT_EQ(1, data.slice_by_state_size());
1476     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1477     EXPECT_TRUE(data.slice_by_state(0).has_value());
1478     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1479               data.slice_by_state(0).value());
1480     ASSERT_EQ(1, data.bucket_info_size());
1481     EXPECT_EQ(70 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1482     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1483     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1484 }
1485 
TEST(DurationMetricE2eTest,TestUploadThreshold)1486 TEST(DurationMetricE2eTest, TestUploadThreshold) {
1487     StatsdConfig config;
1488     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
1489 
1490     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
1491     auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
1492     *config.add_atom_matcher() = screenOnMatcher;
1493     *config.add_atom_matcher() = screenOffMatcher;
1494 
1495     auto durationPredicate = CreateScreenIsOnPredicate();
1496     *config.add_predicate() = durationPredicate;
1497 
1498     int64_t thresholdDurationNs = 30 * 1000 * 1000 * 1000LL;  // 30 seconds
1499     UploadThreshold threshold;
1500     threshold.set_gt_int(thresholdDurationNs);
1501 
1502     int64_t metricId = 123456;
1503     auto durationMetric = config.add_duration_metric();
1504     durationMetric->set_id(metricId);
1505     durationMetric->set_what(durationPredicate.id());
1506     durationMetric->set_bucket(FIVE_MINUTES);
1507     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
1508     *durationMetric->mutable_threshold() = threshold;
1509 
1510     const int64_t baseTimeNs = 0;                                   // 0:00
1511     const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC;  // 0:01
1512     const int64_t bucketSizeNs =
1513             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
1514 
1515     int uid = 12345;
1516     int64_t cfgId = 98765;
1517     ConfigKey cfgKey(uid, cfgId);
1518 
1519     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
1520 
1521     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
1522     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
1523     EXPECT_TRUE(metricsManager->isConfigValid());
1524     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
1525     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
1526     EXPECT_TRUE(metricsManager->isActive());
1527     EXPECT_TRUE(metricProducer->mIsActive);
1528 
1529     std::unique_ptr<LogEvent> event;
1530 
1531     // Screen is off at start of first bucket.
1532     event = CreateScreenStateChangedEvent(configAddedTimeNs,
1533                                           android::view::DISPLAY_STATE_OFF);  // 0:01
1534     processor->OnLogEvent(event.get());
1535 
1536     // Turn screen on.
1537     const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC;  // 0:11
1538     event = CreateScreenStateChangedEvent(durationStartNs, android::view::DISPLAY_STATE_ON);
1539     processor->OnLogEvent(event.get());
1540 
1541     // Turn off screen 30 seconds after turning on.
1542     const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC;  // 0:41
1543     event = CreateScreenStateChangedEvent(durationEndNs, android::view::DISPLAY_STATE_OFF);
1544     processor->OnLogEvent(event.get());
1545 
1546     // Turn screen on in second bucket.
1547     const int64_t duration2StartNs = configAddedTimeNs + bucketSizeNs + 10 * NS_PER_SEC;  // 5:11
1548     event = CreateScreenStateChangedEvent(duration2StartNs, android::view::DISPLAY_STATE_ON);
1549     processor->OnLogEvent(event.get());
1550 
1551     // Turn off screen 31 seconds after turning on.
1552     const int64_t duration2EndNs = duration2StartNs + 31 * NS_PER_SEC;  // 5:42
1553     event = CreateScreenStateChangedEvent(duration2EndNs, android::view::DISPLAY_STATE_OFF);
1554     processor->OnLogEvent(event.get());
1555 
1556     ConfigMetricsReportList reports;
1557     vector<uint8_t> buffer;
1558     processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs * 2 + 1 * NS_PER_SEC, false,
1559                             true, ADB_DUMP, FAST, &buffer);  // 10:01
1560     EXPECT_TRUE(buffer.size() > 0);
1561     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1562     backfillDimensionPath(&reports);
1563     backfillStartEndTimestamp(&reports);
1564     ASSERT_EQ(1, reports.reports_size());
1565     ASSERT_EQ(1, reports.reports(0).metrics_size());
1566     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
1567     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
1568 
1569     StatsLogReport::DurationMetricDataWrapper durationMetrics;
1570     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1571                                     &durationMetrics);
1572     ASSERT_EQ(1, durationMetrics.data_size());
1573 
1574     DurationMetricData data = durationMetrics.data(0);
1575     ASSERT_EQ(1, data.bucket_info_size());
1576     EXPECT_EQ(duration2EndNs - duration2StartNs, data.bucket_info(0).duration_nanos());
1577     EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
1578     EXPECT_EQ(baseTimeNs + bucketSizeNs * 2, data.bucket_info(0).end_bucket_elapsed_nanos());
1579 }
1580 
TEST(DurationMetricE2eTest,TestConditionOnRepeatedEnumField)1581 TEST(DurationMetricE2eTest, TestConditionOnRepeatedEnumField) {
1582     StatsdConfig config;
1583     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
1584 
1585     AtomMatcher repeatedStateFirstOffAtomMatcher = CreateTestAtomRepeatedStateFirstOffAtomMatcher();
1586     AtomMatcher repeatedStateFirstOnAtomMatcher = CreateTestAtomRepeatedStateFirstOnAtomMatcher();
1587     *config.add_atom_matcher() = repeatedStateFirstOffAtomMatcher;
1588     *config.add_atom_matcher() = repeatedStateFirstOnAtomMatcher;
1589 
1590     Predicate durationPredicate = CreateTestAtomRepeatedStateFirstOffPredicate();
1591     *config.add_predicate() = durationPredicate;
1592 
1593     int64_t metricId = 123456;
1594     DurationMetric* durationMetric = config.add_duration_metric();
1595     durationMetric->set_id(metricId);
1596     durationMetric->set_what(durationPredicate.id());
1597     durationMetric->set_bucket(FIVE_MINUTES);
1598     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
1599 
1600     const int64_t baseTimeNs = 0;                                   // 0:00
1601     const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC;  // 0:01
1602     const int64_t bucketSizeNs =
1603             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
1604 
1605     int uid = 12345;
1606     int64_t cfgId = 98765;
1607     ConfigKey cfgKey(uid, cfgId);
1608 
1609     sp<StatsLogProcessor> processor =
1610             CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
1611 
1612     vector<int> intArray = {3, 6};
1613     vector<int64_t> longArray = {1000L, 10002L};
1614     vector<float> floatArray = {0.3f, 0.09f};
1615     vector<string> stringArray = {"str1", "str2"};
1616     int boolArrayLength = 2;
1617     bool boolArray[boolArrayLength];
1618     boolArray[0] = 1;
1619     boolArray[1] = 0;
1620     vector<int> enumArrayOff = {TestAtomReported::OFF, TestAtomReported::ON};
1621     vector<int> enumArrayOn = {TestAtomReported::ON, TestAtomReported::OFF};
1622 
1623     std::vector<std::unique_ptr<LogEvent>> events;
1624     uint64_t falseDurationStartNs = configAddedTimeNs + 10 * NS_PER_SEC;
1625     uint64_t durationStartNs = configAddedTimeNs + 20 * NS_PER_SEC;
1626     uint64_t durationEndNs = durationStartNs + 50 * NS_PER_SEC;
1627 
1628     // Condition false
1629     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(falseDurationStartNs, {}, {},
1630                                                                        {}, {}, {}, 0, enumArrayOn));
1631     // Condition true - start collecting duration.
1632     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(durationStartNs, {}, {}, {},
1633                                                                        {}, {}, 0, enumArrayOff));
1634     // Condition false - stop collecting duration.
1635     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(durationEndNs, {}, {}, {},
1636                                                                        {}, {}, 0, enumArrayOn));
1637 
1638     // Send log events to StatsLogProcessor.
1639     for (auto& event : events) {
1640         processor->OnLogEvent(event.get());
1641     }
1642 
1643     ConfigMetricsReportList reports;
1644     vector<uint8_t> buffer;
1645     processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
1646                             ADB_DUMP, FAST, &buffer);  // 10:01
1647     EXPECT_TRUE(buffer.size() > 0);
1648     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1649     backfillDimensionPath(&reports);
1650     backfillStartEndTimestamp(&reports);
1651     ASSERT_EQ(1, reports.reports_size());
1652     ASSERT_EQ(1, reports.reports(0).metrics_size());
1653     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
1654     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
1655 
1656     StatsLogReport::DurationMetricDataWrapper durationMetrics;
1657     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1658                                     &durationMetrics);
1659     ASSERT_EQ(1, durationMetrics.data_size());
1660 
1661     DurationMetricData data = durationMetrics.data(0);
1662     ASSERT_EQ(1, data.bucket_info_size());
1663     EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
1664     EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
1665     EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
1666 }
1667 
TEST(DurationMetricE2eTest,TestDimensionalSampling)1668 TEST(DurationMetricE2eTest, TestDimensionalSampling) {
1669     ShardOffsetProvider::getInstance().setShardOffset(5);
1670 
1671     StatsdConfig config;
1672     config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
1673 
1674     *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
1675     *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
1676     AtomMatcher stopAllMatcher = CreateScheduleScheduledJobAtomMatcher();
1677     *config.add_atom_matcher() = stopAllMatcher;
1678 
1679     Predicate scheduledJobPredicate = CreateScheduledJobPredicate();
1680     *scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions() =
1681             CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
1682     SimplePredicate* simplePredicate = scheduledJobPredicate.mutable_simple_predicate();
1683     simplePredicate->set_stop_all(stopAllMatcher.id());
1684     *config.add_predicate() = scheduledJobPredicate;
1685 
1686     DurationMetric sampledDurationMetric = createDurationMetric(
1687             "DurationSampledScheduledJobPerUid", scheduledJobPredicate.id(), nullopt, {});
1688     sampledDurationMetric.set_aggregation_type(DurationMetric::SUM);
1689     *sampledDurationMetric.mutable_dimensions_in_what() =
1690             CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
1691     *sampledDurationMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
1692             CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
1693     sampledDurationMetric.mutable_dimensional_sampling_info()->set_shard_count(2);
1694     *config.add_duration_metric() = sampledDurationMetric;
1695 
1696     const int64_t configAddedTimeNs = 1 * NS_PER_SEC;  // 0:01
1697     const int64_t bucketSizeNs =
1698             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
1699 
1700     int uid = 12345;
1701     int64_t cfgId = 98765;
1702     ConfigKey cfgKey(uid, cfgId);
1703 
1704     sp<StatsLogProcessor> processor = CreateStatsLogProcessor(
1705             configAddedTimeNs, configAddedTimeNs, config, cfgKey, nullptr, 0, new UidMap());
1706 
1707     int uid1 = 1001;  // odd hash value
1708     int uid2 = 1002;  // even hash value
1709     int uid3 = 1003;  // odd hash value
1710 
1711     const int64_t durationStartNs1 = 20 * NS_PER_SEC;
1712     const int64_t durationStartNs2 = 40 * NS_PER_SEC;
1713     const int64_t durationStartNs3 = 60 * NS_PER_SEC;
1714     const int64_t durationStartNs4 = 80 * NS_PER_SEC;
1715     const int64_t durationEndNs1 = 100 * NS_PER_SEC;
1716     const int64_t durationEndNs2 = 110 * NS_PER_SEC;
1717     const int64_t stopAllNs = 130 * NS_PER_SEC;
1718     const int64_t durationEndNs3 = 150 * NS_PER_SEC;
1719     const int64_t durationEndNs4 = 200 * NS_PER_SEC;
1720 
1721     std::vector<std::unique_ptr<LogEvent>> events;
1722     events.push_back(CreateStartScheduledJobEvent(durationStartNs1, {uid1}, {"App1"}, "job1"));
1723     events.push_back(CreateStartScheduledJobEvent(durationStartNs2, {uid2}, {"App2"}, "job2"));
1724     events.push_back(CreateStartScheduledJobEvent(durationStartNs3, {uid3}, {"App3"}, "job3"));
1725     events.push_back(CreateFinishScheduledJobEvent(durationEndNs1, {uid1}, {"App1"}, "job1"));
1726     events.push_back(CreateFinishScheduledJobEvent(durationEndNs2, {uid2}, {"App2"}, "job2"));
1727     // This event should pass the sample check regardless of the uid.
1728     events.push_back(CreateScheduleScheduledJobEvent(stopAllNs, {uid2}, {"App2"}, "job2"));
1729     // These events shouldn't do anything since all jobs were stopped with the cancel event.
1730     events.push_back(CreateFinishScheduledJobEvent(durationEndNs3, {uid3}, {"App3"}, "job3"));
1731 
1732     // Send log events to StatsLogProcessor.
1733     for (auto& event : events) {
1734         processor->OnLogEvent(event.get());
1735     }
1736 
1737     ConfigMetricsReportList reports;
1738     vector<uint8_t> buffer;
1739     processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
1740                             FAST, &buffer);
1741     EXPECT_TRUE(buffer.size() > 0);
1742     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1743     backfillDimensionPath(&reports);
1744     backfillStartEndTimestamp(&reports);
1745 
1746     ASSERT_EQ(1, reports.reports_size());
1747     ASSERT_EQ(1, reports.reports(0).metrics_size());
1748     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
1749     StatsLogReport::DurationMetricDataWrapper durationMetrics;
1750     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1751                                     &durationMetrics);
1752     ASSERT_EQ(2, durationMetrics.data_size());
1753 
1754     // Only Uid 1 and 3 are logged. (odd hash value) + (offset of 5) % (shard count of 2) = 0
1755     DurationMetricData data = durationMetrics.data(0);
1756     ValidateAttributionUidDimension(data.dimensions_in_what(), util::SCHEDULED_JOB_STATE_CHANGED,
1757                                     uid1);
1758     ValidateDurationBucket(data.bucket_info(0), configAddedTimeNs, configAddedTimeNs + bucketSizeNs,
1759                            durationEndNs1 - durationStartNs1);
1760 
1761     data = durationMetrics.data(1);
1762     ValidateAttributionUidDimension(data.dimensions_in_what(), util::SCHEDULED_JOB_STATE_CHANGED,
1763                                     uid3);
1764     ValidateDurationBucket(data.bucket_info(0), configAddedTimeNs, configAddedTimeNs + bucketSizeNs,
1765                            stopAllNs - durationStartNs3);
1766 }
1767 
1768 #else
1769 GTEST_LOG_(INFO) << "This test does nothing.\n";
1770 #endif
1771 
1772 }  // namespace statsd
1773 }  // namespace os
1774 }  // namespace android
1775