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