Home | History | Annotate | Download | only in e2e
      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