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 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 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 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 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 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 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