1 // Copyright (C) 2017 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 namespace { 30 31 StatsdConfig CreateCountMetric_NoLink_CombinationCondition_Config() { 32 StatsdConfig config; 33 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. 34 auto screenBrightnessChangeAtomMatcher = CreateScreenBrightnessChangedAtomMatcher(); 35 *config.add_atom_matcher() = screenBrightnessChangeAtomMatcher; 36 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); 37 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); 38 *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher(); 39 *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher(); 40 41 auto screenIsOffPredicate = CreateScreenIsOffPredicate(); 42 *config.add_predicate() = screenIsOffPredicate; 43 44 auto holdingWakelockPredicate = CreateHoldingWakelockPredicate(); 45 // The predicate is dimensioning by any attribution node and both by uid and tag. 46 *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = 47 CreateAttributionUidAndTagDimensions(android::util::WAKELOCK_STATE_CHANGED, 48 {Position::FIRST}); 49 *config.add_predicate() = holdingWakelockPredicate; 50 51 auto combinationPredicate = config.add_predicate(); 52 combinationPredicate->set_id(987654); 53 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); 54 addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); 55 addPredicateToPredicateCombination(holdingWakelockPredicate, combinationPredicate); 56 57 auto metric = config.add_count_metric(); 58 metric->set_id(StringToId("ScreenBrightnessChangeMetric")); 59 metric->set_what(screenBrightnessChangeAtomMatcher.id()); 60 metric->set_condition(combinationPredicate->id()); 61 *metric->mutable_dimensions_in_what() = 62 CreateDimensions(android::util::SCREEN_BRIGHTNESS_CHANGED, {1 /* level */}); 63 *metric->mutable_dimensions_in_condition() = CreateAttributionUidDimensions( 64 android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); 65 metric->set_bucket(FIVE_MINUTES); 66 return config; 67 } 68 69 } // namespace 70 71 TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition) { 72 ConfigKey cfgKey; 73 auto config = CreateCountMetric_NoLink_CombinationCondition_Config(); 74 int64_t bucketStartTimeNs = 10000000000; 75 int64_t bucketSizeNs = 76 TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL; 77 78 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); 79 EXPECT_EQ(processor->mMetricsManagers.size(), 1u); 80 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); 81 82 std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"), 83 CreateAttribution(222, "GMSCoreModule1"), 84 CreateAttribution(222, "GMSCoreModule2")}; 85 86 std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(333, "App2"), 87 CreateAttribution(222, "GMSCoreModule1"), 88 CreateAttribution(555, "GMSCoreModule2")}; 89 90 std::vector<std::unique_ptr<LogEvent>> events; 91 events.push_back( 92 CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10)); 93 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 94 bucketStartTimeNs + 100)); 95 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 96 bucketStartTimeNs + bucketSizeNs + 1)); 97 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 98 bucketStartTimeNs + 2 * bucketSizeNs - 10)); 99 100 events.push_back(CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 200)); 101 events.push_back( 102 CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1)); 103 104 events.push_back(CreateAcquireWakelockEvent(attributions2, "wl2", 105 bucketStartTimeNs + bucketSizeNs - 100)); 106 events.push_back(CreateReleaseWakelockEvent(attributions2, "wl2", 107 bucketStartTimeNs + 2 * bucketSizeNs - 50)); 108 109 events.push_back(CreateScreenBrightnessChangedEvent(123, bucketStartTimeNs + 11)); 110 events.push_back(CreateScreenBrightnessChangedEvent(123, bucketStartTimeNs + 101)); 111 events.push_back(CreateScreenBrightnessChangedEvent(123, bucketStartTimeNs + 201)); 112 events.push_back(CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + 203)); 113 events.push_back( 114 CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + bucketSizeNs - 99)); 115 events.push_back(CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + bucketSizeNs - 2)); 116 events.push_back(CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + bucketSizeNs - 1)); 117 events.push_back(CreateScreenBrightnessChangedEvent(456, bucketStartTimeNs + bucketSizeNs + 2)); 118 events.push_back( 119 CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + 2 * bucketSizeNs - 11)); 120 events.push_back( 121 CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + 2 * bucketSizeNs - 9)); 122 events.push_back( 123 CreateScreenBrightnessChangedEvent(789, bucketStartTimeNs + 2 * bucketSizeNs - 1)); 124 125 sortLogEventsByTimestamp(&events); 126 127 for (const auto& event : events) { 128 processor->OnLogEvent(event.get()); 129 } 130 131 ConfigMetricsReportList reports; 132 vector<uint8_t> buffer; 133 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP, 134 &buffer); 135 EXPECT_TRUE(buffer.size() > 0); 136 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); 137 backfillDimensionPath(&reports); 138 backfillStringInReport(&reports); 139 backfillStartEndTimestamp(&reports); 140 141 EXPECT_EQ(reports.reports_size(), 1); 142 EXPECT_EQ(reports.reports(0).metrics_size(), 1); 143 StatsLogReport::CountMetricDataWrapper countMetrics; 144 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics); 145 146 EXPECT_EQ(countMetrics.data_size(), 7); 147 auto data = countMetrics.data(0); 148 EXPECT_EQ(data.bucket_info_size(), 1); 149 EXPECT_EQ(data.bucket_info(0).count(), 1); 150 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 151 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 152 EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); 153 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 154 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 155 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 123); 156 EXPECT_FALSE(data.dimensions_in_condition().has_field()); 157 158 data = countMetrics.data(1); 159 EXPECT_EQ(data.bucket_info_size(), 1); 160 EXPECT_EQ(data.bucket_info(0).count(), 1); 161 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 162 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 163 EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); 164 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 165 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 166 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 123); 167 ValidateAttributionUidDimension(data.dimensions_in_condition(), 168 android::util::WAKELOCK_STATE_CHANGED, 111); 169 170 data = countMetrics.data(2); 171 EXPECT_EQ(data.bucket_info_size(), 1); 172 EXPECT_EQ(data.bucket_info(0).count(), 3); 173 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 174 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 175 EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); 176 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 177 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 178 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 456); 179 ValidateAttributionUidDimension(data.dimensions_in_condition(), 180 android::util::WAKELOCK_STATE_CHANGED, 111); 181 182 data = countMetrics.data(3); 183 EXPECT_EQ(data.bucket_info_size(), 2); 184 EXPECT_EQ(data.bucket_info(0).count(), 2); 185 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 186 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 187 EXPECT_EQ(data.bucket_info(1).count(), 1); 188 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 189 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); 190 EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); 191 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 192 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 193 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 456); 194 ValidateAttributionUidDimension(data.dimensions_in_condition(), 195 android::util::WAKELOCK_STATE_CHANGED, 333); 196 197 data = countMetrics.data(4); 198 EXPECT_EQ(data.bucket_info_size(), 1); 199 EXPECT_EQ(data.bucket_info(0).count(), 2); 200 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 201 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); 202 EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); 203 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 204 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 205 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 789); 206 EXPECT_FALSE(data.dimensions_in_condition().has_field()); 207 208 data = countMetrics.data(5); 209 EXPECT_EQ(data.bucket_info_size(), 1); 210 EXPECT_EQ(data.bucket_info(0).count(), 1); 211 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 212 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 213 EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); 214 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 215 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 216 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 789); 217 ValidateAttributionUidDimension(data.dimensions_in_condition(), 218 android::util::WAKELOCK_STATE_CHANGED, 111); 219 220 data = countMetrics.data(6); 221 EXPECT_EQ(data.bucket_info_size(), 1); 222 EXPECT_EQ(data.bucket_info(0).count(), 1); 223 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 224 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 225 EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); 226 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 227 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 228 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 789); 229 ValidateAttributionUidDimension(data.dimensions_in_condition(), 230 android::util::WAKELOCK_STATE_CHANGED, 333); 231 } 232 233 namespace { 234 235 StatsdConfig CreateCountMetric_Link_CombinationCondition() { 236 StatsdConfig config; 237 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. 238 auto appCrashMatcher = CreateProcessCrashAtomMatcher(); 239 *config.add_atom_matcher() = appCrashMatcher; 240 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); 241 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); 242 *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); 243 *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); 244 245 auto screenIsOffPredicate = CreateScreenIsOffPredicate(); 246 auto isSyncingPredicate = CreateIsSyncingPredicate(); 247 auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); 248 *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED, 249 {Position::FIRST}); 250 syncDimension->add_child()->set_field(2 /* name field*/); 251 252 *config.add_predicate() = screenIsOffPredicate; 253 *config.add_predicate() = isSyncingPredicate; 254 auto combinationPredicate = config.add_predicate(); 255 combinationPredicate->set_id(987654); 256 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); 257 addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); 258 addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); 259 260 auto metric = config.add_count_metric(); 261 metric->set_bucket(FIVE_MINUTES); 262 metric->set_id(StringToId("AppCrashMetric")); 263 metric->set_what(appCrashMatcher.id()); 264 metric->set_condition(combinationPredicate->id()); 265 *metric->mutable_dimensions_in_what() = 266 CreateDimensions(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1 /* uid */}); 267 *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( 268 android::util::SYNC_STATE_CHANGED, {Position::FIRST}); 269 270 // Links between crash atom and condition of app is in syncing. 271 auto links = metric->add_links(); 272 links->set_condition(isSyncingPredicate.id()); 273 auto dimensionWhat = links->mutable_fields_in_what(); 274 dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); 275 dimensionWhat->add_child()->set_field(1); // uid field. 276 *links->mutable_fields_in_condition() = 277 CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST}); 278 return config; 279 } 280 281 } // namespace 282 283 TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition) { 284 ConfigKey cfgKey; 285 auto config = CreateCountMetric_Link_CombinationCondition(); 286 int64_t bucketStartTimeNs = 10000000000; 287 int64_t bucketSizeNs = 288 TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL; 289 290 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); 291 EXPECT_EQ(processor->mMetricsManagers.size(), 1u); 292 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); 293 std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"), 294 CreateAttribution(222, "GMSCoreModule1"), 295 CreateAttribution(222, "GMSCoreModule2")}; 296 297 std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(333, "App2"), 298 CreateAttribution(222, "GMSCoreModule1"), 299 CreateAttribution(555, "GMSCoreModule2")}; 300 301 std::vector<std::unique_ptr<LogEvent>> events; 302 303 events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 11)); 304 events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 101)); 305 events.push_back(CreateAppCrashEvent(222, bucketStartTimeNs + 101)); 306 307 events.push_back(CreateAppCrashEvent(222, bucketStartTimeNs + 201)); 308 events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 211)); 309 events.push_back(CreateAppCrashEvent(333, bucketStartTimeNs + 211)); 310 311 events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 401)); 312 events.push_back(CreateAppCrashEvent(333, bucketStartTimeNs + 401)); 313 events.push_back(CreateAppCrashEvent(555, bucketStartTimeNs + 401)); 314 315 events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + bucketSizeNs + 301)); 316 events.push_back(CreateAppCrashEvent(333, bucketStartTimeNs + bucketSizeNs + 301)); 317 318 events.push_back(CreateAppCrashEvent(777, bucketStartTimeNs + bucketSizeNs + 701)); 319 320 events.push_back( 321 CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10)); 322 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 323 bucketStartTimeNs + 100)); 324 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 325 bucketStartTimeNs + 202)); 326 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 327 bucketStartTimeNs + bucketSizeNs + 700)); 328 329 events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200)); 330 events.push_back( 331 CreateSyncEndEvent(attributions1, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300)); 332 333 events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400)); 334 events.push_back( 335 CreateSyncEndEvent(attributions1, "ReadDoc", bucketStartTimeNs + bucketSizeNs - 1)); 336 337 events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 400)); 338 events.push_back( 339 CreateSyncEndEvent(attributions2, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 600)); 340 341 sortLogEventsByTimestamp(&events); 342 343 for (const auto& event : events) { 344 processor->OnLogEvent(event.get()); 345 } 346 347 ConfigMetricsReportList reports; 348 vector<uint8_t> buffer; 349 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP, 350 &buffer); 351 EXPECT_TRUE(buffer.size() > 0); 352 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); 353 backfillDimensionPath(&reports); 354 backfillStringInReport(&reports); 355 backfillStartEndTimestamp(&reports); 356 357 EXPECT_EQ(reports.reports_size(), 1); 358 EXPECT_EQ(reports.reports(0).metrics_size(), 1); 359 StatsLogReport::CountMetricDataWrapper countMetrics; 360 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics); 361 362 EXPECT_EQ(countMetrics.data_size(), 5); 363 auto data = countMetrics.data(0); 364 EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); 365 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 366 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 367 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); 368 EXPECT_FALSE(data.dimensions_in_condition().has_field()); 369 EXPECT_EQ(data.bucket_info_size(), 1); 370 EXPECT_EQ(data.bucket_info(0).count(), 1); 371 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 372 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 373 374 data = countMetrics.data(1); 375 EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); 376 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 377 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 378 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); 379 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), 380 android::util::SYNC_STATE_CHANGED, 111, "App1"); 381 EXPECT_EQ(data.bucket_info_size(), 1); 382 EXPECT_EQ(data.bucket_info(0).count(), 2); 383 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 384 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 385 386 data = countMetrics.data(2); 387 EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); 388 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 389 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 390 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 222); 391 EXPECT_FALSE(data.dimensions_in_condition().has_field()); 392 EXPECT_EQ(data.bucket_info_size(), 1); 393 EXPECT_EQ(data.bucket_info(0).count(), 2); 394 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 395 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 396 397 data = countMetrics.data(3); 398 EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); 399 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 400 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 401 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 333); 402 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), 403 android::util::SYNC_STATE_CHANGED, 333, "App2"); 404 EXPECT_EQ(data.bucket_info_size(), 2); 405 EXPECT_EQ(data.bucket_info(0).count(), 1); 406 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 407 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 408 EXPECT_EQ(data.bucket_info(1).count(), 1); 409 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 410 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); 411 412 data = countMetrics.data(4); 413 EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); 414 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); 415 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 416 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 777); 417 EXPECT_FALSE(data.dimensions_in_condition().has_field()); 418 EXPECT_EQ(data.bucket_info_size(), 1); 419 EXPECT_EQ(data.bucket_info(0).count(), 1); 420 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 421 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); 422 } 423 424 namespace { 425 426 StatsdConfig CreateDurationMetricConfig_NoLink_CombinationCondition( 427 DurationMetric::AggregationType aggregationType) { 428 StatsdConfig config; 429 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. 430 *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher(); 431 *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher(); 432 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); 433 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); 434 *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); 435 *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); 436 437 auto inBatterySaverModePredicate = CreateBatterySaverModePredicate(); 438 439 auto screenIsOffPredicate = CreateScreenIsOffPredicate(); 440 auto isSyncingPredicate = CreateIsSyncingPredicate(); 441 auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); 442 *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED, 443 {Position::FIRST}); 444 syncDimension->add_child()->set_field(2 /* name field */); 445 446 *config.add_predicate() = inBatterySaverModePredicate; 447 *config.add_predicate() = screenIsOffPredicate; 448 *config.add_predicate() = isSyncingPredicate; 449 auto combinationPredicate = config.add_predicate(); 450 combinationPredicate->set_id(987654); 451 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); 452 addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); 453 addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); 454 455 auto metric = config.add_duration_metric(); 456 metric->set_bucket(FIVE_MINUTES); 457 metric->set_id(StringToId("BatterySaverModeDurationMetric")); 458 metric->set_what(inBatterySaverModePredicate.id()); 459 metric->set_condition(combinationPredicate->id()); 460 metric->set_aggregation_type(aggregationType); 461 *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( 462 android::util::SYNC_STATE_CHANGED, {Position::FIRST}); 463 return config; 464 } 465 466 } // namespace 467 468 TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition) { 469 for (auto aggregationType : { DurationMetric::MAX_SPARSE, DurationMetric::SUM}) { 470 ConfigKey cfgKey; 471 auto config = CreateDurationMetricConfig_NoLink_CombinationCondition(aggregationType); 472 int64_t bucketStartTimeNs = 10000000000; 473 int64_t bucketSizeNs = 474 TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; 475 476 auto processor = CreateStatsLogProcessor( 477 bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); 478 EXPECT_EQ(processor->mMetricsManagers.size(), 1u); 479 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); 480 481 std::vector<AttributionNodeInternal> attributions1 = { 482 CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), 483 CreateAttribution(222, "GMSCoreModule2")}; 484 485 std::vector<AttributionNodeInternal> attributions2 = { 486 CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), 487 CreateAttribution(555, "GMSCoreModule2")}; 488 489 std::vector<std::unique_ptr<LogEvent>> events; 490 491 events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 1)); 492 events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 101)); 493 events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 110)); 494 495 events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 201)); 496 events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 500)); 497 498 events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 600)); 499 events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + bucketSizeNs + 850)); 500 501 events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + bucketSizeNs + 870)); 502 events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + bucketSizeNs + 900)); 503 504 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 505 bucketStartTimeNs + 10)); 506 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 507 bucketStartTimeNs + 100)); 508 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 509 bucketStartTimeNs + 202)); 510 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 511 bucketStartTimeNs + bucketSizeNs + 800)); 512 513 events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200)); 514 events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", 515 bucketStartTimeNs + bucketSizeNs + 300)); 516 517 events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400)); 518 events.push_back( 519 CreateSyncEndEvent(attributions1, "ReadDoc", bucketStartTimeNs + bucketSizeNs - 1)); 520 521 events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 401)); 522 events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", 523 bucketStartTimeNs + bucketSizeNs + 700)); 524 525 sortLogEventsByTimestamp(&events); 526 527 for (const auto& event : events) { 528 processor->OnLogEvent(event.get()); 529 } 530 531 ConfigMetricsReportList reports; 532 vector<uint8_t> buffer; 533 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP, 534 &buffer); 535 EXPECT_TRUE(buffer.size() > 0); 536 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); 537 backfillDimensionPath(&reports); 538 backfillStringInReport(&reports); 539 backfillStartEndTimestamp(&reports); 540 541 EXPECT_EQ(reports.reports_size(), 1); 542 EXPECT_EQ(reports.reports(0).metrics_size(), 1); 543 StatsLogReport::DurationMetricDataWrapper metrics; 544 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(), &metrics); 545 546 EXPECT_EQ(metrics.data_size(), 3); 547 auto data = metrics.data(0); 548 EXPECT_FALSE(data.dimensions_in_what().has_field()); 549 EXPECT_FALSE(data.dimensions_in_condition().has_field()); 550 if (aggregationType == DurationMetric::SUM) { 551 EXPECT_EQ(data.bucket_info_size(), 2); 552 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9); 553 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 554 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), 555 bucketStartTimeNs + bucketSizeNs); 556 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 30); 557 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), 558 bucketStartTimeNs + bucketSizeNs); 559 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), 560 bucketStartTimeNs + 2 * bucketSizeNs); 561 } else { 562 EXPECT_EQ(data.bucket_info_size(), 2); 563 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9); 564 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 565 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), 566 bucketStartTimeNs + bucketSizeNs); 567 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 30); 568 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), 569 bucketStartTimeNs + bucketSizeNs); 570 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), 571 bucketStartTimeNs + 2 * bucketSizeNs); 572 } 573 574 data = metrics.data(1); 575 EXPECT_FALSE(data.dimensions_in_what().has_field()); 576 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), 577 android::util::SYNC_STATE_CHANGED, 111, "App1"); 578 EXPECT_EQ(data.bucket_info_size(), 2); 579 580 if (aggregationType == DurationMetric::SUM) { 581 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201 + bucketSizeNs - 600); 582 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 300); 583 } else { 584 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201); 585 EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 300); 586 } 587 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 588 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), 589 bucketStartTimeNs + bucketSizeNs); 590 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), 591 bucketStartTimeNs + bucketSizeNs); 592 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), 593 bucketStartTimeNs + 2 * bucketSizeNs); 594 595 data = metrics.data(2); 596 EXPECT_FALSE(data.dimensions_in_what().has_field()); 597 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), 598 android::util::SYNC_STATE_CHANGED, 333, "App2"); 599 EXPECT_EQ(data.bucket_info_size(), 2); 600 if (aggregationType == DurationMetric::SUM) { 601 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401 + bucketSizeNs - 600); 602 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); 603 } else { 604 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401); 605 EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs + 700 - 600); 606 } 607 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 608 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), 609 bucketStartTimeNs + bucketSizeNs); 610 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), 611 bucketStartTimeNs + bucketSizeNs); 612 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), 613 bucketStartTimeNs + 2 * bucketSizeNs); 614 } 615 } 616 617 namespace { 618 619 StatsdConfig CreateDurationMetricConfig_Link_CombinationCondition( 620 DurationMetric::AggregationType aggregationType) { 621 StatsdConfig config; 622 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. 623 *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher(); 624 *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher(); 625 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); 626 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); 627 *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); 628 *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); 629 630 auto screenIsOffPredicate = CreateScreenIsOffPredicate(); 631 auto isSyncingPredicate = CreateIsSyncingPredicate(); 632 auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); 633 *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED, 634 {Position::FIRST}); 635 syncDimension->add_child()->set_field(2 /* name field */); 636 637 auto isInBackgroundPredicate = CreateIsInBackgroundPredicate(); 638 *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() = 639 CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */}); 640 641 *config.add_predicate() = screenIsOffPredicate; 642 *config.add_predicate() = isSyncingPredicate; 643 *config.add_predicate() = isInBackgroundPredicate; 644 auto combinationPredicate = config.add_predicate(); 645 combinationPredicate->set_id(987654); 646 combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); 647 addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); 648 addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); 649 650 auto metric = config.add_duration_metric(); 651 metric->set_bucket(FIVE_MINUTES); 652 metric->set_id(StringToId("AppInBackgroundMetric")); 653 metric->set_what(isInBackgroundPredicate.id()); 654 metric->set_condition(combinationPredicate->id()); 655 metric->set_aggregation_type(aggregationType); 656 *metric->mutable_dimensions_in_what() = 657 CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */}); 658 *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( 659 android::util::SYNC_STATE_CHANGED, {Position::FIRST}); 660 661 // Links between crash atom and condition of app is in syncing. 662 auto links = metric->add_links(); 663 links->set_condition(isSyncingPredicate.id()); 664 auto dimensionWhat = links->mutable_fields_in_what(); 665 dimensionWhat->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED); 666 dimensionWhat->add_child()->set_field(1); // uid field. 667 *links->mutable_fields_in_condition() = 668 CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST}); 669 return config; 670 } 671 672 } // namespace 673 674 TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_OR_CombinationCondition) { 675 for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) { 676 ConfigKey cfgKey; 677 auto config = CreateDurationMetricConfig_Link_CombinationCondition(aggregationType); 678 int64_t bucketStartTimeNs = 10000000000; 679 int64_t bucketSizeNs = 680 TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; 681 682 auto processor = CreateStatsLogProcessor( 683 bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); 684 EXPECT_EQ(processor->mMetricsManagers.size(), 1u); 685 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); 686 687 std::vector<AttributionNodeInternal> attributions1 = { 688 CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), 689 CreateAttribution(222, "GMSCoreModule2")}; 690 691 std::vector<AttributionNodeInternal> attributions2 = { 692 CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), 693 CreateAttribution(555, "GMSCoreModule2")}; 694 695 std::vector<std::unique_ptr<LogEvent>> events; 696 697 events.push_back(CreateMoveToBackgroundEvent(111, bucketStartTimeNs + 101)); 698 events.push_back(CreateMoveToForegroundEvent(111, bucketStartTimeNs + 110)); 699 700 events.push_back(CreateMoveToBackgroundEvent(111, bucketStartTimeNs + 201)); 701 events.push_back(CreateMoveToForegroundEvent(111, bucketStartTimeNs + bucketSizeNs + 100)); 702 703 events.push_back(CreateMoveToBackgroundEvent(333, bucketStartTimeNs + 399)); 704 events.push_back(CreateMoveToForegroundEvent(333, bucketStartTimeNs + bucketSizeNs + 800)); 705 706 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 707 bucketStartTimeNs + 10)); 708 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 709 bucketStartTimeNs + 100)); 710 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 711 bucketStartTimeNs + 202)); 712 events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 713 bucketStartTimeNs + bucketSizeNs + 801)); 714 715 events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200)); 716 events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", 717 bucketStartTimeNs + bucketSizeNs + 300)); 718 719 events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400)); 720 events.push_back( 721 CreateSyncEndEvent(attributions1, "ReadDoc", bucketStartTimeNs + bucketSizeNs - 1)); 722 723 events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 401)); 724 events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", 725 bucketStartTimeNs + bucketSizeNs + 700)); 726 727 sortLogEventsByTimestamp(&events); 728 729 for (const auto& event : events) { 730 processor->OnLogEvent(event.get()); 731 } 732 733 ConfigMetricsReportList reports; 734 vector<uint8_t> buffer; 735 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP, 736 &buffer); 737 EXPECT_TRUE(buffer.size() > 0); 738 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); 739 backfillDimensionPath(&reports); 740 backfillStringInReport(&reports); 741 backfillStartEndTimestamp(&reports); 742 743 EXPECT_EQ(reports.reports_size(), 1); 744 EXPECT_EQ(reports.reports(0).metrics_size(), 1); 745 StatsLogReport::DurationMetricDataWrapper metrics; 746 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(), &metrics); 747 748 EXPECT_EQ(metrics.data_size(), 3); 749 auto data = metrics.data(0); 750 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 751 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); 752 EXPECT_FALSE(data.dimensions_in_condition().has_field()); 753 EXPECT_EQ(data.bucket_info_size(), 1); 754 EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9); 755 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 756 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 757 758 data = metrics.data(1); 759 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 760 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); 761 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), 762 android::util::SYNC_STATE_CHANGED, 111, "App1"); 763 if (aggregationType == DurationMetric::SUM) { 764 EXPECT_EQ(data.bucket_info_size(), 2); 765 EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 201); 766 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); 767 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 768 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), 769 bucketStartTimeNs + bucketSizeNs); 770 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), 771 bucketStartTimeNs + bucketSizeNs); 772 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), 773 bucketStartTimeNs + 2 * bucketSizeNs); 774 } else { 775 EXPECT_EQ(data.bucket_info_size(), 1); 776 EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs + 100 - 201); 777 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), 778 bucketStartTimeNs + bucketSizeNs); 779 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), 780 bucketStartTimeNs + 2 * bucketSizeNs); 781 } 782 783 data = metrics.data(2); 784 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); 785 EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 333); 786 ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), 787 android::util::SYNC_STATE_CHANGED, 333, "App2"); 788 if (aggregationType == DurationMetric::SUM) { 789 EXPECT_EQ(data.bucket_info_size(), 2); 790 EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 401); 791 EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); 792 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 793 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), 794 bucketStartTimeNs + bucketSizeNs); 795 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), 796 bucketStartTimeNs + bucketSizeNs); 797 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), 798 bucketStartTimeNs + 2 * bucketSizeNs); 799 } else { 800 EXPECT_EQ(data.bucket_info_size(), 1); 801 EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs + 299); 802 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), 803 bucketStartTimeNs + bucketSizeNs); 804 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), 805 bucketStartTimeNs + 2 * bucketSizeNs); 806 } 807 } 808 } 809 810 #else 811 GTEST_LOG_(INFO) << "This test does nothing.\n"; 812 #endif 813 814 } // namespace statsd 815 } // namespace os 816 } // namespace android 817