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 "src/StatsLogProcessor.h"
18 #include "src/stats_log_util.h"
19 #include "tests/statsd_test_util.h"
20 
21 #include <vector>
22 
23 namespace android {
24 namespace os {
25 namespace statsd {
26 
27 #ifdef __ANDROID__
28 
TEST(DurationMetricE2eTest,TestOneBucket)29 TEST(DurationMetricE2eTest, TestOneBucket) {
30     StatsdConfig config;
31     config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
32 
33     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
34     auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
35     *config.add_atom_matcher() = screenOnMatcher;
36     *config.add_atom_matcher() = screenOffMatcher;
37 
38     auto durationPredicate = CreateScreenIsOnPredicate();
39     *config.add_predicate() = durationPredicate;
40 
41     int64_t metricId = 123456;
42     auto durationMetric = config.add_duration_metric();
43     durationMetric->set_id(metricId);
44     durationMetric->set_what(durationPredicate.id());
45     durationMetric->set_bucket(FIVE_MINUTES);
46     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
47 
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     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
61     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
62     EXPECT_TRUE(metricsManager->isConfigValid());
63     EXPECT_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(
72             android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 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(android::view::DISPLAY_STATE_ON, durationStartNs);
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(android::view::DISPLAY_STATE_OFF, durationEndNs);
83     processor->OnLogEvent(event.get());
84 
85     event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 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     EXPECT_EQ(1, reports.reports_size());
97     EXPECT_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     const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
102             reports.reports(0).metrics(0).duration_metrics();
103     EXPECT_EQ(1, durationMetrics.data_size());
104 
105     auto data = durationMetrics.data(0);
106     EXPECT_EQ(1, data.bucket_info_size());
107     EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
108     EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
109     EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
110 }
111 
TEST(DurationMetricE2eTest,TestTwoBuckets)112 TEST(DurationMetricE2eTest, TestTwoBuckets) {
113     StatsdConfig config;
114     config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
115 
116     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
117     auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
118     *config.add_atom_matcher() = screenOnMatcher;
119     *config.add_atom_matcher() = screenOffMatcher;
120 
121     auto durationPredicate = CreateScreenIsOnPredicate();
122     *config.add_predicate() = durationPredicate;
123 
124     int64_t metricId = 123456;
125     auto durationMetric = config.add_duration_metric();
126     durationMetric->set_id(metricId);
127     durationMetric->set_what(durationPredicate.id());
128     durationMetric->set_bucket(FIVE_MINUTES);
129     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
130 
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     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
144     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
145     EXPECT_TRUE(metricsManager->isConfigValid());
146     EXPECT_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(
155             android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 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(android::view::DISPLAY_STATE_ON, durationStartNs);
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(android::view::DISPLAY_STATE_OFF, durationEndNs);
166     processor->OnLogEvent(event.get());
167 
168     event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 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, true,
174                             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     EXPECT_EQ(1, reports.reports_size());
180     EXPECT_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     const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
185             reports.reports(0).metrics(0).duration_metrics();
186     EXPECT_EQ(1, durationMetrics.data_size());
187 
188     auto data = durationMetrics.data(0);
189     EXPECT_EQ(1, data.bucket_info_size());
190 
191     auto bucketInfo = data.bucket_info(0);
192     EXPECT_EQ(0, bucketInfo.bucket_num());
193     EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
194     EXPECT_EQ(configAddedTimeNs, bucketInfo.start_bucket_elapsed_nanos());
195     EXPECT_EQ(baseTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
196 }
197 
TEST(DurationMetricE2eTest,TestWithActivation)198 TEST(DurationMetricE2eTest, TestWithActivation) {
199     StatsdConfig config;
200     config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
201 
202     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
203     auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
204     auto crashMatcher = CreateProcessCrashAtomMatcher();
205     *config.add_atom_matcher() = screenOnMatcher;
206     *config.add_atom_matcher() = screenOffMatcher;
207     *config.add_atom_matcher() = crashMatcher;
208 
209     auto durationPredicate = CreateScreenIsOnPredicate();
210     *config.add_predicate() = durationPredicate;
211 
212     int64_t metricId = 123456;
213     auto durationMetric = config.add_duration_metric();
214     durationMetric->set_id(metricId);
215     durationMetric->set_what(durationPredicate.id());
216     durationMetric->set_bucket(FIVE_MINUTES);
217     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
218 
219     auto metric_activation1 = config.add_metric_activation();
220     metric_activation1->set_metric_id(metricId);
221     auto event_activation1 = metric_activation1->add_event_activation();
222     event_activation1->set_atom_matcher_id(crashMatcher.id());
223     event_activation1->set_ttl_seconds(30); // 30 secs.
224 
225     const int64_t bucketStartTimeNs = 10000000000;
226     const int64_t bucketSizeNs =
227             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
228 
229     int uid = 12345;
230     int64_t cfgId = 98765;
231     ConfigKey cfgKey(uid, cfgId);
232 
233     sp<UidMap> m = new UidMap();
234     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
235     sp<AlarmMonitor> anomalyAlarmMonitor;
236     sp<AlarmMonitor> subscriberAlarmMonitor;
237     vector<int64_t> activeConfigsBroadcast;
238 
239     int broadcastCount = 0;
240     StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
241             bucketStartTimeNs, [](const ConfigKey& key) { return true; },
242             [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
243                     const vector<int64_t>& activeConfigs) {
244                 broadcastCount++;
245                 EXPECT_EQ(broadcastUid, uid);
246                 activeConfigsBroadcast.clear();
247                 activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
248                         activeConfigs.begin(), activeConfigs.end());
249                 return true;
250             });
251 
252     processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config); // 0:00
253 
254     EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
255     sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
256     EXPECT_TRUE(metricsManager->isConfigValid());
257     EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
258     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
259     auto& eventActivationMap = metricProducer->mEventActivationMap;
260 
261     EXPECT_FALSE(metricsManager->isActive());
262     EXPECT_FALSE(metricProducer->mIsActive);
263     EXPECT_EQ(eventActivationMap.size(), 1u);
264     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
265     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
266     EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
267     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
268 
269     std::unique_ptr<LogEvent> event;
270 
271     // Turn screen off.
272     event = CreateScreenStateChangedEvent(
273             android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 2 * NS_PER_SEC); // 0:02
274     processor.OnLogEvent(event.get());
275 
276     // Turn screen on.
277     const int64_t durationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:05
278     event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
279     processor.OnLogEvent(event.get());
280 
281     // Activate metric.
282     const int64_t activationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:10
283     const int64_t activationEndNs =
284             activationStartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 0:40
285     event = CreateAppCrashEvent(111, activationStartNs);
286     processor.OnLogEvent(event.get());
287     EXPECT_TRUE(metricsManager->isActive());
288     EXPECT_TRUE(metricProducer->mIsActive);
289     EXPECT_EQ(broadcastCount, 1);
290     EXPECT_EQ(activeConfigsBroadcast.size(), 1);
291     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
292     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
293     EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
294     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
295 
296     // Expire activation.
297     const int64_t expirationNs = activationEndNs + 7 * NS_PER_SEC;
298     event = CreateScreenBrightnessChangedEvent(64, expirationNs); // 0:47
299     processor.OnLogEvent(event.get());
300     EXPECT_FALSE(metricsManager->isActive());
301     EXPECT_FALSE(metricProducer->mIsActive);
302     EXPECT_EQ(broadcastCount, 2);
303     EXPECT_EQ(activeConfigsBroadcast.size(), 0);
304     EXPECT_EQ(eventActivationMap.size(), 1u);
305     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
306     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
307     EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
308     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
309 
310     // Turn off screen 10 seconds after activation expiration.
311     const int64_t durationEndNs = activationEndNs + 10 * NS_PER_SEC; // 0:50
312     event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
313     processor.OnLogEvent(event.get());
314 
315     // Turn screen on.
316     const int64_t duration2StartNs = durationEndNs + 5 * NS_PER_SEC; // 0:55
317     event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
318     processor.OnLogEvent(event.get());
319 
320     // Turn off screen.
321     const int64_t duration2EndNs = duration2StartNs + 10 * NS_PER_SEC; // 1:05
322     event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, duration2EndNs);
323     processor.OnLogEvent(event.get());
324 
325     // Activate metric.
326     const int64_t activation2StartNs = duration2EndNs + 5 * NS_PER_SEC; // 1:10
327     const int64_t activation2EndNs =
328             activation2StartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 1:40
329     event = CreateAppCrashEvent(211, activation2StartNs);
330     processor.OnLogEvent(event.get());
331     EXPECT_TRUE(metricsManager->isActive());
332     EXPECT_TRUE(metricProducer->mIsActive);
333     EXPECT_EQ(broadcastCount, 3);
334     EXPECT_EQ(activeConfigsBroadcast.size(), 1);
335     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
336     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
337     EXPECT_EQ(eventActivationMap[2]->start_ns, activation2StartNs);
338     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
339 
340     ConfigMetricsReportList reports;
341     vector<uint8_t> buffer;
342     processor.onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
343                             ADB_DUMP, FAST, &buffer); // 5:01
344     EXPECT_TRUE(buffer.size() > 0);
345     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
346     backfillDimensionPath(&reports);
347     backfillStartEndTimestamp(&reports);
348     EXPECT_EQ(1, reports.reports_size());
349     EXPECT_EQ(1, reports.reports(0).metrics_size());
350     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
351     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
352 
353     const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
354             reports.reports(0).metrics(0).duration_metrics();
355     EXPECT_EQ(1, durationMetrics.data_size());
356 
357     auto data = durationMetrics.data(0);
358     EXPECT_EQ(1, data.bucket_info_size());
359 
360     auto bucketInfo = data.bucket_info(0);
361     EXPECT_EQ(0, bucketInfo.bucket_num());
362     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
363     EXPECT_EQ(expirationNs, bucketInfo.end_bucket_elapsed_nanos());
364     EXPECT_EQ(expirationNs - durationStartNs, bucketInfo.duration_nanos());
365 }
366 
TEST(DurationMetricE2eTest,TestWithCondition)367 TEST(DurationMetricE2eTest, TestWithCondition) {
368     StatsdConfig config;
369     config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
370     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
371     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
372     *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
373     *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
374 
375     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
376     *config.add_predicate() = holdingWakelockPredicate;
377 
378     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
379     *config.add_predicate() = isInBackgroundPredicate;
380 
381     auto durationMetric = config.add_duration_metric();
382     durationMetric->set_id(StringToId("WakelockDuration"));
383     durationMetric->set_what(holdingWakelockPredicate.id());
384     durationMetric->set_condition(isInBackgroundPredicate.id());
385     durationMetric->set_aggregation_type(DurationMetric::SUM);
386     durationMetric->set_bucket(FIVE_MINUTES);
387 
388     ConfigKey cfgKey;
389     uint64_t bucketStartTimeNs = 10000000000;
390     uint64_t bucketSizeNs =
391             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
392     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
393     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
394     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
395     EXPECT_TRUE(metricsManager->isConfigValid());
396     EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
397     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
398     auto& eventActivationMap = metricProducer->mEventActivationMap;
399     EXPECT_TRUE(metricsManager->isActive());
400     EXPECT_TRUE(metricProducer->mIsActive);
401     EXPECT_TRUE(eventActivationMap.empty());
402 
403     int appUid = 123;
404     std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
405 
406     auto event = CreateAcquireWakelockEvent(
407             attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
408     processor->OnLogEvent(event.get());
409 
410     event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
411     processor->OnLogEvent(event.get());
412 
413     event = CreateMoveToForegroundEvent(
414             appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
415     processor->OnLogEvent(event.get());
416 
417     event = CreateReleaseWakelockEvent(
418             attributions1, "wl1", bucketStartTimeNs + 4 * 60 * NS_PER_SEC); // 4:00
419     processor->OnLogEvent(event.get());
420 
421     vector<uint8_t> buffer;
422     ConfigMetricsReportList reports;
423     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
424                             ADB_DUMP, FAST, &buffer);
425     EXPECT_GT(buffer.size(), 0);
426     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
427     backfillDimensionPath(&reports);
428     backfillStringInReport(&reports);
429     backfillStartEndTimestamp(&reports);
430 
431     EXPECT_EQ(1, reports.reports_size());
432     EXPECT_EQ(1, reports.reports(0).metrics_size());
433     EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
434 
435     auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
436 
437     // Validate bucket info.
438     EXPECT_EQ(1, data.bucket_info_size());
439 
440     auto bucketInfo = data.bucket_info(0);
441     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
442     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
443     EXPECT_EQ((2 * 60 + 53) * NS_PER_SEC, bucketInfo.duration_nanos());
444 }
445 
TEST(DurationMetricE2eTest,TestWithSlicedCondition)446 TEST(DurationMetricE2eTest, TestWithSlicedCondition) {
447     StatsdConfig config;
448     config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
449     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
450     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
451     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
452     *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
453     *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
454 
455     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
456     // The predicate is dimensioning by first attribution node by uid.
457     FieldMatcher dimensions = CreateAttributionUidDimensions(
458             android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
459     *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
460     *config.add_predicate() = holdingWakelockPredicate;
461 
462     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
463     *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
464         CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
465     *config.add_predicate() = isInBackgroundPredicate;
466 
467     auto durationMetric = config.add_duration_metric();
468     durationMetric->set_id(StringToId("WakelockDuration"));
469     durationMetric->set_what(holdingWakelockPredicate.id());
470     durationMetric->set_condition(isInBackgroundPredicate.id());
471     durationMetric->set_aggregation_type(DurationMetric::SUM);
472     // The metric is dimensioning by first attribution node and only by uid.
473     *durationMetric->mutable_dimensions_in_what() =
474         CreateAttributionUidDimensions(
475             android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
476     durationMetric->set_bucket(FIVE_MINUTES);
477 
478     // Links between wakelock state atom and condition of app is in background.
479     auto links = durationMetric->add_links();
480     links->set_condition(isInBackgroundPredicate.id());
481     auto dimensionWhat = links->mutable_fields_in_what();
482     dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
483     dimensionWhat->add_child()->set_field(1);  // uid field.
484     *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
485             android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
486 
487     ConfigKey cfgKey;
488     uint64_t bucketStartTimeNs = 10000000000;
489     uint64_t bucketSizeNs =
490             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
491     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
492     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
493     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
494     EXPECT_TRUE(metricsManager->isConfigValid());
495     EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
496     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
497     auto& eventActivationMap = metricProducer->mEventActivationMap;
498     EXPECT_TRUE(metricsManager->isActive());
499     EXPECT_TRUE(metricProducer->mIsActive);
500     EXPECT_TRUE(eventActivationMap.empty());
501 
502     int appUid = 123;
503     std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
504 
505     auto event = CreateAcquireWakelockEvent(
506             attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
507     processor->OnLogEvent(event.get());
508 
509     event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
510     processor->OnLogEvent(event.get());
511 
512     event = CreateReleaseWakelockEvent(
513             attributions1, "wl1", bucketStartTimeNs + 60 * NS_PER_SEC); // 1:00
514     processor->OnLogEvent(event.get());
515 
516 
517     event = CreateMoveToForegroundEvent(
518             appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
519     processor->OnLogEvent(event.get());
520 
521     vector<uint8_t> buffer;
522     ConfigMetricsReportList reports;
523     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
524                             ADB_DUMP, FAST, &buffer);
525     EXPECT_GT(buffer.size(), 0);
526     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
527     backfillDimensionPath(&reports);
528     backfillStringInReport(&reports);
529     backfillStartEndTimestamp(&reports);
530 
531     EXPECT_EQ(1, reports.reports_size());
532     EXPECT_EQ(1, reports.reports(0).metrics_size());
533     EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
534 
535     auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
536     // Validate dimension value.
537     ValidateAttributionUidDimension(data.dimensions_in_what(),
538                                     android::util::WAKELOCK_STATE_CHANGED, appUid);
539     // Validate bucket info.
540     EXPECT_EQ(1, data.bucket_info_size());
541 
542     auto bucketInfo = data.bucket_info(0);
543     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
544     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
545     EXPECT_EQ(38 * NS_PER_SEC, bucketInfo.duration_nanos());
546 }
547 
TEST(DurationMetricE2eTest,TestWithActivationAndSlicedCondition)548 TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition) {
549     StatsdConfig config;
550     config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
551     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
552     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
553     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
554     *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
555     *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
556     *config.add_atom_matcher() = screenOnMatcher;
557 
558     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
559     // The predicate is dimensioning by first attribution node by uid.
560     FieldMatcher dimensions = CreateAttributionUidDimensions(
561             android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
562     *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
563     *config.add_predicate() = holdingWakelockPredicate;
564 
565     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
566     *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
567         CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
568     *config.add_predicate() = isInBackgroundPredicate;
569 
570     auto durationMetric = config.add_duration_metric();
571     durationMetric->set_id(StringToId("WakelockDuration"));
572     durationMetric->set_what(holdingWakelockPredicate.id());
573     durationMetric->set_condition(isInBackgroundPredicate.id());
574     durationMetric->set_aggregation_type(DurationMetric::SUM);
575     // The metric is dimensioning by first attribution node and only by uid.
576     *durationMetric->mutable_dimensions_in_what() =
577         CreateAttributionUidDimensions(
578             android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
579     durationMetric->set_bucket(FIVE_MINUTES);
580 
581     // Links between wakelock state atom and condition of app is in background.
582     auto links = durationMetric->add_links();
583     links->set_condition(isInBackgroundPredicate.id());
584     auto dimensionWhat = links->mutable_fields_in_what();
585     dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
586     dimensionWhat->add_child()->set_field(1);  // uid field.
587     *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
588             android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
589 
590     auto metric_activation1 = config.add_metric_activation();
591     metric_activation1->set_metric_id(durationMetric->id());
592     auto event_activation1 = metric_activation1->add_event_activation();
593     event_activation1->set_atom_matcher_id(screenOnMatcher.id());
594     event_activation1->set_ttl_seconds(60 * 2);  // 2 minutes.
595 
596     ConfigKey cfgKey;
597     uint64_t bucketStartTimeNs = 10000000000;
598     uint64_t bucketSizeNs =
599             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
600     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
601     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
602     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
603     EXPECT_TRUE(metricsManager->isConfigValid());
604     EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
605     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
606     auto& eventActivationMap = metricProducer->mEventActivationMap;
607     EXPECT_FALSE(metricsManager->isActive());
608     EXPECT_FALSE(metricProducer->mIsActive);
609     EXPECT_EQ(eventActivationMap.size(), 1u);
610     EXPECT_TRUE(eventActivationMap.find(4) != eventActivationMap.end());
611     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
612     EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
613     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
614 
615     int appUid = 123;
616     std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
617 
618     auto event = CreateAcquireWakelockEvent(
619             attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
620     processor->OnLogEvent(event.get());
621     EXPECT_FALSE(metricsManager->isActive());
622     EXPECT_FALSE(metricProducer->mIsActive);
623     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
624     EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
625     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
626 
627     event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
628     processor->OnLogEvent(event.get());
629     EXPECT_FALSE(metricsManager->isActive());
630     EXPECT_FALSE(metricProducer->mIsActive);
631     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
632     EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
633     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
634 
635     const int64_t durationStartNs = bucketStartTimeNs + 30 * NS_PER_SEC; // 0:30
636     event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
637     processor->OnLogEvent(event.get());
638     EXPECT_TRUE(metricsManager->isActive());
639     EXPECT_TRUE(metricProducer->mIsActive);
640     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
641     EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
642     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
643 
644     const int64_t durationEndNs =
645             durationStartNs + (event_activation1->ttl_seconds() + 30) * NS_PER_SEC; // 3:00
646     event = CreateAppCrashEvent(333, durationEndNs);
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, durationStartNs);
652     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
653 
654     event = CreateMoveToForegroundEvent(
655             appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
656     processor->OnLogEvent(event.get());
657 
658     event = CreateReleaseWakelockEvent(
659             attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 17) * NS_PER_SEC); // 4:17
660     processor->OnLogEvent(event.get());
661 
662     event = CreateMoveToBackgroundEvent(
663             appUid, bucketStartTimeNs + (4 * 60 + 20) * NS_PER_SEC); // 4:20
664     processor->OnLogEvent(event.get());
665 
666     event = CreateAcquireWakelockEvent(
667             attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 25) * NS_PER_SEC); // 4:25
668     processor->OnLogEvent(event.get());
669 
670     const int64_t duration2StartNs = bucketStartTimeNs + (4 * 60 + 30) * NS_PER_SEC; // 4:30
671     event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
672     processor->OnLogEvent(event.get());
673     EXPECT_TRUE(metricsManager->isActive());
674     EXPECT_TRUE(metricProducer->mIsActive);
675     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
676     EXPECT_EQ(eventActivationMap[4]->start_ns, duration2StartNs);
677     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
678 
679     vector<uint8_t> buffer;
680     ConfigMetricsReportList reports;
681     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
682                             ADB_DUMP, FAST, &buffer);
683     EXPECT_GT(buffer.size(), 0);
684     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
685     backfillDimensionPath(&reports);
686     backfillStringInReport(&reports);
687     backfillStartEndTimestamp(&reports);
688 
689     EXPECT_EQ(1, reports.reports_size());
690     EXPECT_EQ(1, reports.reports(0).metrics_size());
691     EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
692 
693     auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
694     // Validate dimension value.
695     ValidateAttributionUidDimension(data.dimensions_in_what(),
696                                     android::util::WAKELOCK_STATE_CHANGED, appUid);
697     // Validate bucket info.
698     EXPECT_EQ(2, data.bucket_info_size());
699 
700     auto bucketInfo = data.bucket_info(0);
701     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
702     EXPECT_EQ(durationEndNs, bucketInfo.end_bucket_elapsed_nanos());
703     EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
704 
705     bucketInfo = data.bucket_info(1);
706     EXPECT_EQ(durationEndNs, bucketInfo.start_bucket_elapsed_nanos());
707     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
708     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - duration2StartNs, bucketInfo.duration_nanos());
709 }
710 
711 #else
712 GTEST_LOG_(INFO) << "This test does nothing.\n";
713 #endif
714 
715 }  // namespace statsd
716 }  // namespace os
717 }  // namespace android
718