diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 766c2d1db5a32..e7f1caf269328 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -385,7 +385,11 @@ void StatsLogProcessor::onConfigMetricsReportLocked(const ConfigKey& key, // This skips the uid map if it's an empty config. if (it->second->getNumMetrics() > 0) { uint64_t uidMapToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP); - mUidMap->appendUidMap(dumpTimeStampNs, key, &str_set, proto); + if (it->second->hashStringInReport()) { + mUidMap->appendUidMap(dumpTimeStampNs, key, &str_set, proto); + } else { + mUidMap->appendUidMap(dumpTimeStampNs, key, nullptr, proto); + } proto->end(uidMapToken); } diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index 2d14b05c8f5b5..4fac0e1a141be 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -74,6 +74,8 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config, mAllPeriodicAlarmTrackers, mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap, mNoReportMetricIds); + mHashStringsInReport = config.hash_strings_in_metric_report(); + if (config.allowed_log_source_size() == 0) { mConfigValid = false; ALOGE("Log source whitelist is empty! This config won't get any data. Suggest adding at " @@ -201,8 +203,13 @@ void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs, if (mNoReportMetricIds.find(producer->getMetricId()) == mNoReportMetricIds.end()) { uint64_t token = protoOutput->start( FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_METRICS); - producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, str_set, - protoOutput); + if (mHashStringsInReport) { + producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, str_set, + protoOutput); + } else { + producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, nullptr, + protoOutput); + } protoOutput->end(token); } else { producer->clearPastBuckets(dumpTimeStampNs); diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index e143b5a582dd3..6f4db48def86b 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -77,6 +77,10 @@ public: return mTtlNs <= 0 || timestampNs < mTtlEndNs; }; + inline bool hashStringInReport() const { + return mHashStringsInReport; + }; + void refreshTtl(const int64_t currentTimestampNs) { if (mTtlNs > 0) { mTtlEndNs = currentTimestampNs + mTtlNs; @@ -118,6 +122,8 @@ private: bool mConfigValid = false; + bool mHashStringsInReport = false; + const int64_t mTtlNs; int64_t mTtlEndNs; diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto index eb77299846e6d..cf55300005555 100644 --- a/cmds/statsd/src/statsd_config.proto +++ b/cmds/statsd/src/statsd_config.proto @@ -364,6 +364,8 @@ message StatsdConfig { optional int64 ttl_in_seconds = 15; + optional bool hash_strings_in_metric_report = 16 [default = true]; + // Field number 1000 is reserved for later use. reserved 1000; } diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp index dff79771f14d7..f03821432cc1e 100644 --- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp +++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp @@ -29,7 +29,8 @@ namespace statsd { namespace { StatsdConfig CreateDurationMetricConfig_NoLink_AND_CombinationCondition( - DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition) { + DurationMetric::AggregationType aggregationType, bool addExtraDimensionInCondition, + bool hashStringInReport) { StatsdConfig config; config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher(); @@ -54,6 +55,7 @@ StatsdConfig CreateDurationMetricConfig_NoLink_AND_CombinationCondition( syncDimension->add_child()->set_field(2 /* name field*/); } + config.set_hash_strings_in_metric_report(hashStringInReport); *config.add_predicate() = scheduledJobPredicate; *config.add_predicate() = screenIsOffPredicate; *config.add_predicate() = isSyncingPredicate; @@ -80,258 +82,283 @@ StatsdConfig CreateDurationMetricConfig_NoLink_AND_CombinationCondition( } // namespace TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition) { - for (bool isDimensionInConditionSubSetOfConditionTrackerDimension : { true, false }) { - for (auto aggregationType : {DurationMetric::MAX_SPARSE, DurationMetric::SUM}) { - ConfigKey cfgKey; - auto config = CreateDurationMetricConfig_NoLink_AND_CombinationCondition( - aggregationType, isDimensionInConditionSubSetOfConditionTrackerDimension); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; + for (const bool hashStringInReport : { true, false }) { + for (bool isDimensionInConditionSubSetOfConditionTrackerDimension : { true, false }) { + for (auto aggregationType : {DurationMetric::MAX_SPARSE, DurationMetric::SUM}) { + ConfigKey cfgKey; + auto config = CreateDurationMetricConfig_NoLink_AND_CombinationCondition( + aggregationType, isDimensionInConditionSubSetOfConditionTrackerDimension, + hashStringInReport); + int64_t bucketStartTimeNs = 10000000000; + int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis( + config.duration_metric(0).bucket()) * 1000000LL; - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + auto processor = CreateStatsLogProcessor( + bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - std::vector attributions1 = { - CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; + std::vector attributions1 = { + CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; - std::vector attributions2 = { - CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; + std::vector attributions2 = { + CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(555, "GMSCoreModule2")}; - std::vector> events; + std::vector> events; - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 11)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 40)); + events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, + bucketStartTimeNs + 11)); + events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, + bucketStartTimeNs + 40)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 102)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 450)); + events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, + bucketStartTimeNs + 102)); + events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, + bucketStartTimeNs + 450)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 650)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + bucketSizeNs + 100)); + events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, + bucketStartTimeNs + 650)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_ON, + bucketStartTimeNs + bucketSizeNs + 100)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + bucketSizeNs + 640)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + bucketSizeNs + 650)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_OFF, + bucketStartTimeNs + bucketSizeNs + 640)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_ON, + bucketStartTimeNs + bucketSizeNs + 650)); - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(9999, "")}, "job0", bucketStartTimeNs + 2)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(9999, "")}, "job0",bucketStartTimeNs + 101)); + events.push_back(CreateStartScheduledJobEvent( + {CreateAttribution(9999, "")}, "job0", bucketStartTimeNs + 2)); + events.push_back(CreateFinishScheduledJobEvent( + {CreateAttribution(9999, "")}, "job0",bucketStartTimeNs + 101)); - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(9999, "")}, "job2", bucketStartTimeNs + 201)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(9999, "")}, "job2",bucketStartTimeNs + 500)); + events.push_back(CreateStartScheduledJobEvent( + {CreateAttribution(9999, "")}, "job2", bucketStartTimeNs + 201)); + events.push_back(CreateFinishScheduledJobEvent( + {CreateAttribution(9999, "")}, "job2",bucketStartTimeNs + 500)); - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(8888, "")}, "job2", bucketStartTimeNs + 600)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(8888, "")}, "job2",bucketStartTimeNs + bucketSizeNs + 850)); + events.push_back(CreateStartScheduledJobEvent( + {CreateAttribution(8888, "")}, "job2", bucketStartTimeNs + 600)); + events.push_back(CreateFinishScheduledJobEvent( + {CreateAttribution(8888, "")}, "job2", + bucketStartTimeNs + bucketSizeNs + 850)); - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 600)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(8888, "")}, "job1", bucketStartTimeNs + bucketSizeNs + 900)); + events.push_back(CreateStartScheduledJobEvent( + {CreateAttribution(8888, "")}, "job1", + bucketStartTimeNs + bucketSizeNs + 600)); + events.push_back(CreateFinishScheduledJobEvent( + {CreateAttribution(8888, "")}, "job1", + bucketStartTimeNs + bucketSizeNs + 900)); - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 10)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 50)); + events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", + bucketStartTimeNs + 10)); + events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", + bucketStartTimeNs + 50)); - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 200)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 300)); + events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", + bucketStartTimeNs + 200)); + events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", + bucketStartTimeNs + bucketSizeNs + 300)); - events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", - bucketStartTimeNs + 400)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); + events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", + bucketStartTimeNs + 400)); + events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc", + bucketStartTimeNs + bucketSizeNs - 1)); - events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", - bucketStartTimeNs + 401)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 700)); + events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", + bucketStartTimeNs + 401)); + events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", + bucketStartTimeNs + bucketSizeNs + 700)); - sortLogEventsByTimestamp(&events); + sortLogEventsByTimestamp(&events); - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } + for (const auto& event : events) { + processor->OnLogEvent(event.get()); + } - ConfigMetricsReportList reports; - vector buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, - ADB_DUMP, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); + ConfigMetricsReportList reports; + vector buffer; + processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, + ADB_DUMP, &buffer); + EXPECT_TRUE(buffer.size() > 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::DurationMetricDataWrapper metrics; - sortMetricDataByDimensionsValue( - reports.reports(0).metrics(0).duration_metrics(), &metrics); - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(metrics.data_size(), 4); - auto data = metrics.data(0); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job0"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40 - 11); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(reports.reports_size(), 1); + EXPECT_EQ(reports.reports(0).metrics_size(), 1); + StatsLogReport::DurationMetricDataWrapper metrics; + sortMetricDataByDimensionsValue( + reports.reports(0).metrics(0).duration_metrics(), &metrics); + if (aggregationType == DurationMetric::SUM) { + EXPECT_EQ(metrics.data_size(), 4); + auto data = metrics.data(0); + EXPECT_EQ(data.dimensions_in_what().field(), + android::util::SCHEDULED_JOB_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), + 2); // job name field + EXPECT_EQ(data.dimensions_in_what().value_tuple(). + dimensions_value(0).value_str(), + "job0"); // job name + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), + android::util::SYNC_STATE_CHANGED, 111, "App1"); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40 - 11); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), + bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); - data = metrics.data(1); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job1"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 10); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); + data = metrics.data(1); + EXPECT_EQ(data.dimensions_in_what().field(), + android::util::SCHEDULED_JOB_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), + 2); // job name field + EXPECT_EQ(data.dimensions_in_what().value_tuple(). + dimensions_value(0).value_str(), + "job1"); // job name + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), + android::util::SYNC_STATE_CHANGED, 333, "App2"); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 10); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + 2 * bucketSizeNs); - data = metrics.data(2); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); + data = metrics.data(2); + EXPECT_EQ(data.dimensions_in_what().field(), + android::util::SCHEDULED_JOB_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), + 2); // job name field + EXPECT_EQ(data.dimensions_in_what().value_tuple(). + dimensions_value(0).value_str(), + "job2"); // job name + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), + android::util::SYNC_STATE_CHANGED, 111, "App1"); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201 + bucketSizeNs - 600); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), + bucketStartTimeNs + 2 * bucketSizeNs); - data = metrics.data(3); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100 + 650 - 640); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } else { - EXPECT_EQ(metrics.data_size(), 4); - auto data = metrics.data(0); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job0"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40 - 11); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); + data = metrics.data(3); + EXPECT_EQ(data.dimensions_in_what().field(), + android::util::SCHEDULED_JOB_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), + 2); // job name field + EXPECT_EQ(data.dimensions_in_what().value_tuple(). + dimensions_value(0).value_str(), + "job2"); // job name + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), + android::util::SYNC_STATE_CHANGED, 333, "App2"); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401 + bucketSizeNs - 600); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100 + 650 - 640); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), + bucketStartTimeNs + 2 * bucketSizeNs); + } else { + EXPECT_EQ(metrics.data_size(), 4); + auto data = metrics.data(0); + EXPECT_EQ(data.dimensions_in_what().field(), + android::util::SCHEDULED_JOB_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), + 2); // job name field + EXPECT_EQ(data.dimensions_in_what().value_tuple(). + dimensions_value(0).value_str(), + "job0"); // job name + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), + android::util::SYNC_STATE_CHANGED, 111, "App1"); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 40 - 11); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), + bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); - data = metrics.data(1); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job1"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 10); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); + data = metrics.data(1); + EXPECT_EQ(data.dimensions_in_what().field(), + android::util::SCHEDULED_JOB_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), + 2); // job name field + EXPECT_EQ(data.dimensions_in_what().value_tuple(). + dimensions_value(0).value_str(), + "job1"); // job name + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), + android::util::SYNC_STATE_CHANGED, 333, "App2"); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 10); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + 2 * bucketSizeNs); - data = metrics.data(2); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 111, "App1"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); + data = metrics.data(2); + EXPECT_EQ(data.dimensions_in_what().field(), + android::util::SCHEDULED_JOB_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), + 2); // job name field + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), + "job2"); // job name + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), + android::util::SYNC_STATE_CHANGED, 111, "App1"); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), + bucketStartTimeNs + 2 * bucketSizeNs); - data = metrics.data(3); - EXPECT_EQ(data.dimensions_in_what().field(), - android::util::SCHEDULED_JOB_STATE_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), - 2); // job name field - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), - "job2"); // job name - ValidateAttributionUidAndTagDimension(data.dimensions_in_condition(), - android::util::SYNC_STATE_CHANGED, 333, "App2"); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 110); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); + data = metrics.data(3); + EXPECT_EQ(data.dimensions_in_what().field(), + android::util::SCHEDULED_JOB_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), + 2); // job name field + EXPECT_EQ(data.dimensions_in_what().value_tuple(). + dimensions_value(0).value_str(), + "job2"); // job name + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), + android::util::SYNC_STATE_CHANGED, 333, "App2"); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 110); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), + bucketStartTimeNs + 2 * bucketSizeNs); + } } } } @@ -588,7 +615,7 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationConditi namespace { StatsdConfig CreateDurationMetricConfig_PartialLink_AND_CombinationCondition( - DurationMetric::AggregationType aggregationType) { + DurationMetric::AggregationType aggregationType, bool hashStringInReport) { StatsdConfig config; config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher(); @@ -612,6 +639,7 @@ StatsdConfig CreateDurationMetricConfig_PartialLink_AND_CombinationCondition( auto screenIsOffPredicate = CreateScreenIsOffPredicate(); + config.set_hash_strings_in_metric_report(hashStringInReport); *config.add_predicate() = scheduledJobPredicate; *config.add_predicate() = screenIsOffPredicate; *config.add_predicate() = isSyncingPredicate; @@ -645,242 +673,253 @@ StatsdConfig CreateDurationMetricConfig_PartialLink_AND_CombinationCondition( } // namespace TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_CombinationCondition) { - for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) { - ConfigKey cfgKey; - auto config = - CreateDurationMetricConfig_PartialLink_AND_CombinationCondition(aggregationType); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; + for (const bool hashStringInReport : {true, false}) { + for (auto aggregationType : {DurationMetric::SUM, DurationMetric::MAX_SPARSE}) { + ConfigKey cfgKey; + auto config = + CreateDurationMetricConfig_PartialLink_AND_CombinationCondition( + aggregationType, hashStringInReport); + int64_t bucketStartTimeNs = 10000000000; + int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + auto processor = CreateStatsLogProcessor( + bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - std::vector attributions1 = { - CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(222, "GMSCoreModule2")}; + std::vector attributions1 = { + CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; - std::vector attributions2 = { - CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; + std::vector attributions2 = { + CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(555, "GMSCoreModule2")}; - std::vector attributions3 = { - CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"), - CreateAttribution(555, "GMSCoreModule2")}; + std::vector attributions3 = { + CreateAttribution(444, "App3"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(555, "GMSCoreModule2")}; - std::vector> events; + std::vector> events; - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 55)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 120)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 121)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + 450)); + events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, + bucketStartTimeNs + 55)); + events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, + bucketStartTimeNs + 120)); + events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, + bucketStartTimeNs + 121)); + events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, + bucketStartTimeNs + 450)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, - bucketStartTimeNs + 501)); - events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, - bucketStartTimeNs + bucketSizeNs + 100)); + events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, + bucketStartTimeNs + 501)); + events.push_back(CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, + bucketStartTimeNs + bucketSizeNs + 100)); - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101)); + events.push_back(CreateStartScheduledJobEvent( + {CreateAttribution(111, "App1")}, "job1", bucketStartTimeNs + 1)); + events.push_back(CreateFinishScheduledJobEvent( + {CreateAttribution(111, "App1")}, "job1",bucketStartTimeNs + 101)); - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500)); - events.push_back(CreateStartScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600)); - events.push_back(CreateFinishScheduledJobEvent( - {CreateAttribution(333, "App2")}, "job2", - bucketStartTimeNs + bucketSizeNs + 850)); + events.push_back(CreateStartScheduledJobEvent( + {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 201)); + events.push_back(CreateFinishScheduledJobEvent( + {CreateAttribution(333, "App2")}, "job2",bucketStartTimeNs + 500)); + events.push_back(CreateStartScheduledJobEvent( + {CreateAttribution(333, "App2")}, "job2", bucketStartTimeNs + 600)); + events.push_back(CreateFinishScheduledJobEvent( + {CreateAttribution(333, "App2")}, "job2", + bucketStartTimeNs + bucketSizeNs + 850)); - events.push_back( - CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", - bucketStartTimeNs + bucketSizeNs - 2)); - events.push_back( - CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", - bucketStartTimeNs + bucketSizeNs + 900)); + events.push_back( + CreateStartScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", + bucketStartTimeNs + bucketSizeNs - 2)); + events.push_back( + CreateFinishScheduledJobEvent({CreateAttribution(444, "App3")}, "job3", + bucketStartTimeNs + bucketSizeNs + 900)); - events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 50)); - events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", - bucketStartTimeNs + 110)); + events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", + bucketStartTimeNs + 50)); + events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", + bucketStartTimeNs + 110)); - events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", - bucketStartTimeNs + 300)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", - bucketStartTimeNs + bucketSizeNs + 700)); - events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc", - bucketStartTimeNs + 400)); - events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); + events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", + bucketStartTimeNs + 300)); + events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", + bucketStartTimeNs + bucketSizeNs + 700)); + events.push_back(CreateSyncStartEvent(attributions2, "ReadDoc", + bucketStartTimeNs + 400)); + events.push_back(CreateSyncEndEvent(attributions2, "ReadDoc", + bucketStartTimeNs + bucketSizeNs - 1)); - events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", - bucketStartTimeNs + 550)); - events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", - bucketStartTimeNs + 800)); - events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", - bucketStartTimeNs + bucketSizeNs - 1)); - events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", - bucketStartTimeNs + bucketSizeNs + 700)); + events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", + bucketStartTimeNs + 550)); + events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", + bucketStartTimeNs + 800)); + events.push_back(CreateSyncStartEvent(attributions3, "ReadDoc", + bucketStartTimeNs + bucketSizeNs - 1)); + events.push_back(CreateSyncEndEvent(attributions3, "ReadDoc", + bucketStartTimeNs + bucketSizeNs + 700)); - sortLogEventsByTimestamp(&events); + sortLogEventsByTimestamp(&events); - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } + for (const auto& event : events) { + processor->OnLogEvent(event.get()); + } - ConfigMetricsReportList reports; - vector buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP, - &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - backfillDimensionPath(&reports); - backfillStringInReport(&reports); - backfillStartEndTimestamp(&reports); + ConfigMetricsReportList reports; + vector buffer; + processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, + ADB_DUMP, &buffer); + EXPECT_TRUE(buffer.size() > 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::DurationMetricDataWrapper metrics; - sortMetricDataByDimensionsValue( - reports.reports(0).metrics(0).duration_metrics(), &metrics); - if (aggregationType == DurationMetric::SUM) { - EXPECT_EQ(metrics.data_size(), 4); - auto data = metrics.data(0); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(reports.reports_size(), 1); + EXPECT_EQ(reports.reports(0).metrics_size(), 1); + StatsLogReport::DurationMetricDataWrapper metrics; + sortMetricDataByDimensionsValue( + reports.reports(0).metrics(0).duration_metrics(), &metrics); + if (aggregationType == DurationMetric::SUM) { + EXPECT_EQ(metrics.data_size(), 4); + auto data = metrics.data(0); + ValidateAttributionUidDimension( + data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); + ValidateAttributionUidDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111); + EXPECT_EQ("ReadEmail", + data.dimensions_in_condition().value_tuple(). + dimensions_value(1).value_str()); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), + bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); - data = metrics.data(1); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 1 - 600 + 50); + data = metrics.data(1); + ValidateAttributionUidDimension( + data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); + ValidateAttributionUidDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); + EXPECT_EQ("ReadDoc", + data.dimensions_in_condition().value_tuple(). + dimensions_value(1).value_str()); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 1 - 600 + 50); - data = metrics.data(2); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); + data = metrics.data(2); + ValidateAttributionUidDimension( + data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); + ValidateAttributionUidDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); + EXPECT_EQ("ReadEmail", + data.dimensions_in_condition().value_tuple(). + dimensions_value(1).value_str()); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300 + bucketSizeNs - 600); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), + bucketStartTimeNs + 2 * bucketSizeNs); - data = metrics.data(3); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); - } else { - EXPECT_EQ(metrics.data_size(), 4); - auto data = metrics.data(0); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); + data = metrics.data(3); + ValidateAttributionUidDimension( + data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); + ValidateAttributionUidDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444); + EXPECT_EQ("ReadDoc", + data.dimensions_in_condition().value_tuple(). + dimensions_value(1).value_str()); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 1); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), + bucketStartTimeNs + 2 * bucketSizeNs); + } else { + EXPECT_EQ(metrics.data_size(), 4); + auto data = metrics.data(0); + ValidateAttributionUidDimension( + data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 111); + ValidateAttributionUidDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111); + EXPECT_EQ("ReadEmail", + data.dimensions_in_condition().value_tuple(). + dimensions_value(1).value_str()); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101 - 55); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), + bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); - data = metrics.data(1); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 50); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 1 - 600); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); + data = metrics.data(1); + ValidateAttributionUidDimension( + data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); + ValidateAttributionUidDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); + EXPECT_EQ("ReadDoc", + data.dimensions_in_condition().value_tuple(). + dimensions_value(1).value_str()); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 50); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 1 - 600); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), + bucketStartTimeNs + 2 * bucketSizeNs); - data = metrics.data(2); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); - EXPECT_EQ("ReadEmail", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300); - EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); + data = metrics.data(2); + ValidateAttributionUidDimension( + data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 333); + ValidateAttributionUidDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333); + EXPECT_EQ("ReadEmail", + data.dimensions_in_condition().value_tuple(). + dimensions_value(1).value_str()); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 300); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), + bucketStartTimeNs + 2 * bucketSizeNs); - data = metrics.data(3); - ValidateAttributionUidDimension( - data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); - ValidateAttributionUidDimension( - data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444); - EXPECT_EQ("ReadDoc", - data.dimensions_in_condition().value_tuple().dimensions_value(1).value_str()); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101); - EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), - bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), - bucketStartTimeNs + 2 * bucketSizeNs); + data = metrics.data(3); + ValidateAttributionUidDimension( + data.dimensions_in_what(), android::util::SCHEDULED_JOB_STATE_CHANGED, 444); + ValidateAttributionUidDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 444); + EXPECT_EQ("ReadDoc", + data.dimensions_in_condition().value_tuple(). + dimensions_value(1).value_str()); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 101); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), + bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), + bucketStartTimeNs + 2 * bucketSizeNs); + } } } }