Loading cmds/statsd/src/StatsLogProcessor.cpp +45 −50 Original line number Diff line number Diff line Loading @@ -68,12 +68,8 @@ const int FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS = 6; const int FIELD_ID_DUMP_REPORT_REASON = 8; const int FIELD_ID_STRINGS = 9; const int FIELD_ID_ACTIVE_CONFIG_LIST = 1; const int FIELD_ID_CONFIG_ID = 1; const int FIELD_ID_CONFIG_UID = 2; const int FIELD_ID_ACTIVE_METRIC = 3; const int FIELD_ID_METRIC_ID = 1; const int FIELD_ID_TIME_TO_LIVE_NANOS = 2; // for ActiveConfigList const int FIELD_ID_ACTIVE_CONFIG_LIST_CONFIG = 1; #define NS_PER_HOUR 3600 * NS_PER_SEC Loading Loading @@ -613,7 +609,7 @@ void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key, mOnDiskDataConfigs.insert(key); } void StatsLogProcessor::WriteMetricsActivationToDisk(int64_t currentTimeNs) { void StatsLogProcessor::SaveActiveConfigsToDisk(int64_t currentTimeNs) { std::lock_guard<std::mutex> lock(mMetricsMutex); const int64_t timeNs = getElapsedRealtimeNs(); Loading @@ -629,28 +625,12 @@ void StatsLogProcessor::WriteMetricsActivationToDisk(int64_t currentTimeNs) { mLastActiveMetricsWriteNs = timeNs; ProtoOutputStream proto; for (const auto& pair : mMetricsManagers) { uint64_t activeConfigListToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ACTIVE_CONFIG_LIST); proto.write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_ID, (long long)pair.first.GetId()); proto.write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_UID, pair.first.GetUid()); vector<MetricProducer*> activeMetrics; pair.second->prepForShutDown(currentTimeNs); pair.second->getActiveMetrics(activeMetrics); for (MetricProducer* metric : activeMetrics) { if (metric->isActive()) { uint64_t metricToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ACTIVE_METRIC); proto.write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_ID, (long long)metric->getMetricId()); proto.write(FIELD_TYPE_INT64 | FIELD_ID_TIME_TO_LIVE_NANOS, (long long)metric->getRemainingTtlNs(currentTimeNs)); proto.end(metricToken); } } proto.end(activeConfigListToken); const sp<MetricsManager>& metricsManager = pair.second; uint64_t configToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ACTIVE_CONFIG_LIST_CONFIG); metricsManager->writeActiveConfigToProtoOutputStream(currentTimeNs, &proto); proto.end(configToken); } string file_name = StringPrintf("%s/active_metrics", STATS_ACTIVE_METRIC_DIR); Loading @@ -664,30 +644,45 @@ void StatsLogProcessor::WriteMetricsActivationToDisk(int64_t currentTimeNs) { proto.flush(fd.get()); } void StatsLogProcessor::LoadMetricsActivationFromDisk() { void StatsLogProcessor::LoadActiveConfigsFromDisk() { std::lock_guard<std::mutex> lock(mMetricsMutex); string file_name = StringPrintf("%s/active_metrics", STATS_ACTIVE_METRIC_DIR); int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC); if (fd != -1) { if (-1 == fd) { VLOG("Attempt to read %s but failed", file_name.c_str()); StorageManager::deleteFile(file_name.c_str()); return; } string content; if (android::base::ReadFdToString(fd, &content)) { if (!android::base::ReadFdToString(fd, &content)) { ALOGE("Attempt to read %s but failed", file_name.c_str()); close(fd); StorageManager::deleteFile(file_name.c_str()); return; } close(fd); ActiveConfigList activeConfigList; if (activeConfigList.ParseFromString(content)) { for (int i = 0; i < activeConfigList.active_config_size(); i++) { const auto& config = activeConfigList.active_config(i); ConfigKey key(config.uid(), config.config_id()); if (!activeConfigList.ParseFromString(content)) { ALOGE("Attempt to read %s but failed; failed to load active configs", file_name.c_str()); StorageManager::deleteFile(file_name.c_str()); return; } for (int i = 0; i < activeConfigList.config_size(); i++) { const auto& config = activeConfigList.config(i); ConfigKey key(config.uid(), config.id()); auto it = mMetricsManagers.find(key); if (it == mMetricsManagers.end()) { ALOGE("No config found for config %s", key.ToString().c_str()); continue; } VLOG("Setting active config %s", key.ToString().c_str()); it->second->setActiveMetrics(config, mTimeBaseNs); } } VLOG("Successfully loaded %d active configs.", activeConfigList.active_config_size()); } close(fd); it->second->loadActiveConfig(config, mTimeBaseNs); } VLOG("Successfully loaded %d active configs.", activeConfigList.config_size()); StorageManager::deleteFile(file_name.c_str()); } Loading cmds/statsd/src/StatsLogProcessor.h +7 −4 Original line number Diff line number Diff line Loading @@ -89,11 +89,11 @@ public: void WriteDataToDisk(const DumpReportReason dumpReportReason, const DumpLatency dumpLatency); /* Persist metric activation status onto disk. */ void WriteMetricsActivationToDisk(int64_t currentTimeNs); /* Persist configs containing metrics with active activations to disk. */ void SaveActiveConfigsToDisk(int64_t currentTimeNs); /* Load metric activation status from disk. */ void LoadMetricsActivationFromDisk(); /* Load configs containing metrics with active activations from disk. */ void LoadActiveConfigsFromDisk(); // Reset all configs. void resetConfigs(); Loading Loading @@ -221,6 +221,9 @@ private: FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge); FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead); FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot); FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations); FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivationsDifferentActivationTypes); FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1); FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2); Loading cmds/statsd/src/StatsService.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -986,7 +986,7 @@ Status StatsService::informDeviceShutdown() { ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informDeviceShutdown"); mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST); mProcessor->WriteMetricsActivationToDisk(getElapsedRealtimeNs()); mProcessor->SaveActiveConfigsToDisk(getElapsedRealtimeNs()); return Status::ok(); } Loading Loading @@ -1021,14 +1021,14 @@ Status StatsService::statsCompanionReady() { void StatsService::Startup() { mConfigManager->Startup(); mProcessor->LoadMetricsActivationFromDisk(); mProcessor->LoadActiveConfigsFromDisk(); } void StatsService::Terminate() { ALOGI("StatsService::Terminating"); if (mProcessor != nullptr) { mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED, FAST); mProcessor->WriteMetricsActivationToDisk(getElapsedRealtimeNs()); mProcessor->SaveActiveConfigsToDisk(getElapsedRealtimeNs()); } } Loading cmds/statsd/src/active_config_list.proto +14 −11 Original line number Diff line number Diff line Loading @@ -21,23 +21,26 @@ option java_package = "com.android.os"; option java_multiple_files = true; option java_outer_classname = "ActiveConfigProto"; message ActiveEventActivation { optional int32 atom_matcher_index = 1; // Time left in activation. When this proto is loaded after device boot, // the activation should be set to active for this duration. optional int64 remaining_ttl_nanos = 2; } message ActiveMetric { // metric id optional int64 metric_id = 1; // Remaining time to live in nano seconds. -1 for infinity. optional int64 time_to_live_nanos = 2; optional int64 id = 1; repeated ActiveEventActivation activation = 2; } message ActiveConfig { // config id optional int64 config_id = 1; // config uid optional int64 id = 1; optional int32 uid = 2; // metrics repeated ActiveMetric active_metric = 3; repeated ActiveMetric metric = 3; } // all configs and their metrics on device. message ActiveConfigList { repeated ActiveConfig active_config = 1; repeated ActiveConfig config = 1; } cmds/statsd/src/metrics/MetricProducer.cpp +66 −40 Original line number Diff line number Diff line Loading @@ -18,12 +18,26 @@ #include "Log.h" #include "MetricProducer.h" using android::util::FIELD_COUNT_REPEATED; using android::util::FIELD_TYPE_INT32; using android::util::FIELD_TYPE_INT64; using android::util::FIELD_TYPE_MESSAGE; using android::util::ProtoOutputStream; namespace android { namespace os { namespace statsd { using std::map; // for ActiveMetric const int FIELD_ID_ACTIVE_METRIC_ID = 1; const int FIELD_ID_ACTIVE_METRIC_ACTIVATION = 2; // for ActiveEventActivation const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_ATOM_MATCHER_INDEX = 1; const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS = 2; void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) { if (!mIsActive) { return; Loading Loading @@ -74,7 +88,7 @@ bool MetricProducer::evaluateActiveStateLocked(int64_t elapsedTimestampNs) { bool isActive = mEventActivationMap.empty(); for (auto& it : mEventActivationMap) { if (it.second->state == ActivationState::kActive && elapsedTimestampNs > it.second->ttl_ns + it.second->activation_ns) { elapsedTimestampNs > it.second->ttl_ns + it.second->start_ns) { it.second->state = ActivationState::kNotActive; } if (it.second->state == ActivationState::kActive) { Loading @@ -95,8 +109,8 @@ void MetricProducer::flushIfExpire(int64_t elapsedTimestampNs) { } } void MetricProducer::addActivation(int activationTrackerIndex, int64_t ttl_seconds, int deactivationTrackerIndex) { void MetricProducer::addActivation(int activationTrackerIndex, const ActivationType& activationType, int64_t ttl_seconds, int deactivationTrackerIndex) { std::lock_guard<std::mutex> lock(mMutex); // When a metric producer does not depend on any activation, its mIsActive is true. // Therefore, if this is the 1st activation, mIsActive will turn to false. Otherwise it does not Loading @@ -104,8 +118,8 @@ void MetricProducer::addActivation(int activationTrackerIndex, int64_t ttl_secon if (mEventActivationMap.empty()) { mIsActive = false; } std::shared_ptr<Activation> activation = std::make_shared<Activation>(); activation->ttl_ns = ttl_seconds * NS_PER_SEC; std::shared_ptr<Activation> activation = std::make_shared<Activation>(activationType, ttl_seconds * NS_PER_SEC); mEventActivationMap.emplace(activationTrackerIndex, activation); if (-1 != deactivationTrackerIndex) { mEventDeactivationMap.emplace(deactivationTrackerIndex, activation); Loading @@ -117,13 +131,16 @@ void MetricProducer::activateLocked(int activationTrackerIndex, int64_t elapsedT if (it == mEventActivationMap.end()) { return; } if (mActivationType == MetricActivation::ACTIVATE_ON_BOOT && it->second->state == ActivationState::kNotActive) { it->second->state = ActivationState::kActiveOnBoot; auto& activation = it->second; if (ACTIVATE_ON_BOOT == activation->activationType) { if (ActivationState::kNotActive == activation->state) { activation->state = ActivationState::kActiveOnBoot; } // If the Activation is already active or set to kActiveOnBoot, do nothing. return; } it->second->activation_ns = elapsedTimestampNs; it->second->state = ActivationState::kActive; activation->start_ns = elapsedTimestampNs; activation->state = ActivationState::kActive; mIsActive = true; } Loading @@ -135,46 +152,55 @@ void MetricProducer::cancelEventActivationLocked(int deactivationTrackerIndex) { it->second->state = ActivationState::kNotActive; } void MetricProducer::setActiveLocked(int64_t currentTimeNs, int64_t remainingTtlNs) { void MetricProducer::loadActiveMetricLocked(const ActiveMetric& activeMetric, int64_t currentTimeNs) { if (mEventActivationMap.size() == 0) { return; } for (auto& pair : mEventActivationMap) { auto& activation = pair.second; if (activation->ttl_ns >= remainingTtlNs) { activation->activation_ns = currentTimeNs + remainingTtlNs - activation->ttl_ns; activation->state = kActive; for (int i = 0; i < activeMetric.activation_size(); i++) { const auto& activeEventActivation = activeMetric.activation(i); auto it = mEventActivationMap.find(activeEventActivation.atom_matcher_index()); if (it == mEventActivationMap.end()) { ALOGE("Saved event activation not found"); continue; } auto& activation = it->second; // We don't want to change the ttl for future activations, so we set the start_ns // such that start_ns + ttl_ns == currentTimeNs + remaining_ttl_nanos activation->start_ns = currentTimeNs + activeEventActivation.remaining_ttl_nanos() - activation->ttl_ns; activation->state = ActivationState::kActive; mIsActive = true; VLOG("setting new activation->time to %lld, %lld, %lld", (long long)activation->activation_ns, (long long)currentTimeNs, (long long)remainingTtlNs); return; } } ALOGE("Required ttl is longer than all possible activations."); } int64_t MetricProducer::getRemainingTtlNsLocked(int64_t currentTimeNs) const { int64_t maxTtl = 0; for (const auto& activation : mEventActivationMap) { if (activation.second->state == kActive) { maxTtl = std::max(maxTtl, activation.second->ttl_ns + activation.second->activation_ns - currentTimeNs); } } return maxTtl; } void MetricProducer::prepActiveForBootIfNecessaryLocked(int64_t currentTimeNs) { if (mActivationType != MetricActivation::ACTIVATE_ON_BOOT) { return; } for (auto& activation : mEventActivationMap) { if (activation.second->state == kActiveOnBoot) { activation.second->state = kActive; activation.second->activation_ns = currentTimeNs; mIsActive = true; void MetricProducer::writeActiveMetricToProtoOutputStream( int64_t currentTimeNs, ProtoOutputStream* proto) { proto->write(FIELD_TYPE_INT64 | FIELD_ID_ACTIVE_METRIC_ID, (long long)mMetricId); for (auto& it : mEventActivationMap) { const int atom_matcher_index = it.first; const std::shared_ptr<Activation>& activation = it.second; if (ActivationState::kNotActive == activation->state || (ActivationState::kActive == activation->state && activation->start_ns + activation->ttl_ns < currentTimeNs)) { continue; } const uint64_t activationToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ACTIVE_METRIC_ACTIVATION); proto->write(FIELD_TYPE_INT32 | FIELD_ID_ACTIVE_EVENT_ACTIVATION_ATOM_MATCHER_INDEX, atom_matcher_index); if (ActivationState::kActive == activation->state) { const int64_t remainingTtlNs = activation->start_ns + activation->ttl_ns - currentTimeNs; proto->write(FIELD_TYPE_INT64 | FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS, (long long)remainingTtlNs); } else if (ActivationState::kActiveOnBoot == activation->state) { proto->write(FIELD_TYPE_INT64 | FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS, (long long)activation->ttl_ns); } proto->end(activationToken); } } Loading Loading
cmds/statsd/src/StatsLogProcessor.cpp +45 −50 Original line number Diff line number Diff line Loading @@ -68,12 +68,8 @@ const int FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS = 6; const int FIELD_ID_DUMP_REPORT_REASON = 8; const int FIELD_ID_STRINGS = 9; const int FIELD_ID_ACTIVE_CONFIG_LIST = 1; const int FIELD_ID_CONFIG_ID = 1; const int FIELD_ID_CONFIG_UID = 2; const int FIELD_ID_ACTIVE_METRIC = 3; const int FIELD_ID_METRIC_ID = 1; const int FIELD_ID_TIME_TO_LIVE_NANOS = 2; // for ActiveConfigList const int FIELD_ID_ACTIVE_CONFIG_LIST_CONFIG = 1; #define NS_PER_HOUR 3600 * NS_PER_SEC Loading Loading @@ -613,7 +609,7 @@ void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key, mOnDiskDataConfigs.insert(key); } void StatsLogProcessor::WriteMetricsActivationToDisk(int64_t currentTimeNs) { void StatsLogProcessor::SaveActiveConfigsToDisk(int64_t currentTimeNs) { std::lock_guard<std::mutex> lock(mMetricsMutex); const int64_t timeNs = getElapsedRealtimeNs(); Loading @@ -629,28 +625,12 @@ void StatsLogProcessor::WriteMetricsActivationToDisk(int64_t currentTimeNs) { mLastActiveMetricsWriteNs = timeNs; ProtoOutputStream proto; for (const auto& pair : mMetricsManagers) { uint64_t activeConfigListToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ACTIVE_CONFIG_LIST); proto.write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_ID, (long long)pair.first.GetId()); proto.write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_UID, pair.first.GetUid()); vector<MetricProducer*> activeMetrics; pair.second->prepForShutDown(currentTimeNs); pair.second->getActiveMetrics(activeMetrics); for (MetricProducer* metric : activeMetrics) { if (metric->isActive()) { uint64_t metricToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ACTIVE_METRIC); proto.write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_ID, (long long)metric->getMetricId()); proto.write(FIELD_TYPE_INT64 | FIELD_ID_TIME_TO_LIVE_NANOS, (long long)metric->getRemainingTtlNs(currentTimeNs)); proto.end(metricToken); } } proto.end(activeConfigListToken); const sp<MetricsManager>& metricsManager = pair.second; uint64_t configToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ACTIVE_CONFIG_LIST_CONFIG); metricsManager->writeActiveConfigToProtoOutputStream(currentTimeNs, &proto); proto.end(configToken); } string file_name = StringPrintf("%s/active_metrics", STATS_ACTIVE_METRIC_DIR); Loading @@ -664,30 +644,45 @@ void StatsLogProcessor::WriteMetricsActivationToDisk(int64_t currentTimeNs) { proto.flush(fd.get()); } void StatsLogProcessor::LoadMetricsActivationFromDisk() { void StatsLogProcessor::LoadActiveConfigsFromDisk() { std::lock_guard<std::mutex> lock(mMetricsMutex); string file_name = StringPrintf("%s/active_metrics", STATS_ACTIVE_METRIC_DIR); int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC); if (fd != -1) { if (-1 == fd) { VLOG("Attempt to read %s but failed", file_name.c_str()); StorageManager::deleteFile(file_name.c_str()); return; } string content; if (android::base::ReadFdToString(fd, &content)) { if (!android::base::ReadFdToString(fd, &content)) { ALOGE("Attempt to read %s but failed", file_name.c_str()); close(fd); StorageManager::deleteFile(file_name.c_str()); return; } close(fd); ActiveConfigList activeConfigList; if (activeConfigList.ParseFromString(content)) { for (int i = 0; i < activeConfigList.active_config_size(); i++) { const auto& config = activeConfigList.active_config(i); ConfigKey key(config.uid(), config.config_id()); if (!activeConfigList.ParseFromString(content)) { ALOGE("Attempt to read %s but failed; failed to load active configs", file_name.c_str()); StorageManager::deleteFile(file_name.c_str()); return; } for (int i = 0; i < activeConfigList.config_size(); i++) { const auto& config = activeConfigList.config(i); ConfigKey key(config.uid(), config.id()); auto it = mMetricsManagers.find(key); if (it == mMetricsManagers.end()) { ALOGE("No config found for config %s", key.ToString().c_str()); continue; } VLOG("Setting active config %s", key.ToString().c_str()); it->second->setActiveMetrics(config, mTimeBaseNs); } } VLOG("Successfully loaded %d active configs.", activeConfigList.active_config_size()); } close(fd); it->second->loadActiveConfig(config, mTimeBaseNs); } VLOG("Successfully loaded %d active configs.", activeConfigList.config_size()); StorageManager::deleteFile(file_name.c_str()); } Loading
cmds/statsd/src/StatsLogProcessor.h +7 −4 Original line number Diff line number Diff line Loading @@ -89,11 +89,11 @@ public: void WriteDataToDisk(const DumpReportReason dumpReportReason, const DumpLatency dumpLatency); /* Persist metric activation status onto disk. */ void WriteMetricsActivationToDisk(int64_t currentTimeNs); /* Persist configs containing metrics with active activations to disk. */ void SaveActiveConfigsToDisk(int64_t currentTimeNs); /* Load metric activation status from disk. */ void LoadMetricsActivationFromDisk(); /* Load configs containing metrics with active activations from disk. */ void LoadActiveConfigsFromDisk(); // Reset all configs. void resetConfigs(); Loading Loading @@ -221,6 +221,9 @@ private: FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge); FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead); FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot); FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations); FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivationsDifferentActivationTypes); FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1); FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2); Loading
cmds/statsd/src/StatsService.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -986,7 +986,7 @@ Status StatsService::informDeviceShutdown() { ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informDeviceShutdown"); mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST); mProcessor->WriteMetricsActivationToDisk(getElapsedRealtimeNs()); mProcessor->SaveActiveConfigsToDisk(getElapsedRealtimeNs()); return Status::ok(); } Loading Loading @@ -1021,14 +1021,14 @@ Status StatsService::statsCompanionReady() { void StatsService::Startup() { mConfigManager->Startup(); mProcessor->LoadMetricsActivationFromDisk(); mProcessor->LoadActiveConfigsFromDisk(); } void StatsService::Terminate() { ALOGI("StatsService::Terminating"); if (mProcessor != nullptr) { mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED, FAST); mProcessor->WriteMetricsActivationToDisk(getElapsedRealtimeNs()); mProcessor->SaveActiveConfigsToDisk(getElapsedRealtimeNs()); } } Loading
cmds/statsd/src/active_config_list.proto +14 −11 Original line number Diff line number Diff line Loading @@ -21,23 +21,26 @@ option java_package = "com.android.os"; option java_multiple_files = true; option java_outer_classname = "ActiveConfigProto"; message ActiveEventActivation { optional int32 atom_matcher_index = 1; // Time left in activation. When this proto is loaded after device boot, // the activation should be set to active for this duration. optional int64 remaining_ttl_nanos = 2; } message ActiveMetric { // metric id optional int64 metric_id = 1; // Remaining time to live in nano seconds. -1 for infinity. optional int64 time_to_live_nanos = 2; optional int64 id = 1; repeated ActiveEventActivation activation = 2; } message ActiveConfig { // config id optional int64 config_id = 1; // config uid optional int64 id = 1; optional int32 uid = 2; // metrics repeated ActiveMetric active_metric = 3; repeated ActiveMetric metric = 3; } // all configs and their metrics on device. message ActiveConfigList { repeated ActiveConfig active_config = 1; repeated ActiveConfig config = 1; }
cmds/statsd/src/metrics/MetricProducer.cpp +66 −40 Original line number Diff line number Diff line Loading @@ -18,12 +18,26 @@ #include "Log.h" #include "MetricProducer.h" using android::util::FIELD_COUNT_REPEATED; using android::util::FIELD_TYPE_INT32; using android::util::FIELD_TYPE_INT64; using android::util::FIELD_TYPE_MESSAGE; using android::util::ProtoOutputStream; namespace android { namespace os { namespace statsd { using std::map; // for ActiveMetric const int FIELD_ID_ACTIVE_METRIC_ID = 1; const int FIELD_ID_ACTIVE_METRIC_ACTIVATION = 2; // for ActiveEventActivation const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_ATOM_MATCHER_INDEX = 1; const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS = 2; void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) { if (!mIsActive) { return; Loading Loading @@ -74,7 +88,7 @@ bool MetricProducer::evaluateActiveStateLocked(int64_t elapsedTimestampNs) { bool isActive = mEventActivationMap.empty(); for (auto& it : mEventActivationMap) { if (it.second->state == ActivationState::kActive && elapsedTimestampNs > it.second->ttl_ns + it.second->activation_ns) { elapsedTimestampNs > it.second->ttl_ns + it.second->start_ns) { it.second->state = ActivationState::kNotActive; } if (it.second->state == ActivationState::kActive) { Loading @@ -95,8 +109,8 @@ void MetricProducer::flushIfExpire(int64_t elapsedTimestampNs) { } } void MetricProducer::addActivation(int activationTrackerIndex, int64_t ttl_seconds, int deactivationTrackerIndex) { void MetricProducer::addActivation(int activationTrackerIndex, const ActivationType& activationType, int64_t ttl_seconds, int deactivationTrackerIndex) { std::lock_guard<std::mutex> lock(mMutex); // When a metric producer does not depend on any activation, its mIsActive is true. // Therefore, if this is the 1st activation, mIsActive will turn to false. Otherwise it does not Loading @@ -104,8 +118,8 @@ void MetricProducer::addActivation(int activationTrackerIndex, int64_t ttl_secon if (mEventActivationMap.empty()) { mIsActive = false; } std::shared_ptr<Activation> activation = std::make_shared<Activation>(); activation->ttl_ns = ttl_seconds * NS_PER_SEC; std::shared_ptr<Activation> activation = std::make_shared<Activation>(activationType, ttl_seconds * NS_PER_SEC); mEventActivationMap.emplace(activationTrackerIndex, activation); if (-1 != deactivationTrackerIndex) { mEventDeactivationMap.emplace(deactivationTrackerIndex, activation); Loading @@ -117,13 +131,16 @@ void MetricProducer::activateLocked(int activationTrackerIndex, int64_t elapsedT if (it == mEventActivationMap.end()) { return; } if (mActivationType == MetricActivation::ACTIVATE_ON_BOOT && it->second->state == ActivationState::kNotActive) { it->second->state = ActivationState::kActiveOnBoot; auto& activation = it->second; if (ACTIVATE_ON_BOOT == activation->activationType) { if (ActivationState::kNotActive == activation->state) { activation->state = ActivationState::kActiveOnBoot; } // If the Activation is already active or set to kActiveOnBoot, do nothing. return; } it->second->activation_ns = elapsedTimestampNs; it->second->state = ActivationState::kActive; activation->start_ns = elapsedTimestampNs; activation->state = ActivationState::kActive; mIsActive = true; } Loading @@ -135,46 +152,55 @@ void MetricProducer::cancelEventActivationLocked(int deactivationTrackerIndex) { it->second->state = ActivationState::kNotActive; } void MetricProducer::setActiveLocked(int64_t currentTimeNs, int64_t remainingTtlNs) { void MetricProducer::loadActiveMetricLocked(const ActiveMetric& activeMetric, int64_t currentTimeNs) { if (mEventActivationMap.size() == 0) { return; } for (auto& pair : mEventActivationMap) { auto& activation = pair.second; if (activation->ttl_ns >= remainingTtlNs) { activation->activation_ns = currentTimeNs + remainingTtlNs - activation->ttl_ns; activation->state = kActive; for (int i = 0; i < activeMetric.activation_size(); i++) { const auto& activeEventActivation = activeMetric.activation(i); auto it = mEventActivationMap.find(activeEventActivation.atom_matcher_index()); if (it == mEventActivationMap.end()) { ALOGE("Saved event activation not found"); continue; } auto& activation = it->second; // We don't want to change the ttl for future activations, so we set the start_ns // such that start_ns + ttl_ns == currentTimeNs + remaining_ttl_nanos activation->start_ns = currentTimeNs + activeEventActivation.remaining_ttl_nanos() - activation->ttl_ns; activation->state = ActivationState::kActive; mIsActive = true; VLOG("setting new activation->time to %lld, %lld, %lld", (long long)activation->activation_ns, (long long)currentTimeNs, (long long)remainingTtlNs); return; } } ALOGE("Required ttl is longer than all possible activations."); } int64_t MetricProducer::getRemainingTtlNsLocked(int64_t currentTimeNs) const { int64_t maxTtl = 0; for (const auto& activation : mEventActivationMap) { if (activation.second->state == kActive) { maxTtl = std::max(maxTtl, activation.second->ttl_ns + activation.second->activation_ns - currentTimeNs); } } return maxTtl; } void MetricProducer::prepActiveForBootIfNecessaryLocked(int64_t currentTimeNs) { if (mActivationType != MetricActivation::ACTIVATE_ON_BOOT) { return; } for (auto& activation : mEventActivationMap) { if (activation.second->state == kActiveOnBoot) { activation.second->state = kActive; activation.second->activation_ns = currentTimeNs; mIsActive = true; void MetricProducer::writeActiveMetricToProtoOutputStream( int64_t currentTimeNs, ProtoOutputStream* proto) { proto->write(FIELD_TYPE_INT64 | FIELD_ID_ACTIVE_METRIC_ID, (long long)mMetricId); for (auto& it : mEventActivationMap) { const int atom_matcher_index = it.first; const std::shared_ptr<Activation>& activation = it.second; if (ActivationState::kNotActive == activation->state || (ActivationState::kActive == activation->state && activation->start_ns + activation->ttl_ns < currentTimeNs)) { continue; } const uint64_t activationToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ACTIVE_METRIC_ACTIVATION); proto->write(FIELD_TYPE_INT32 | FIELD_ID_ACTIVE_EVENT_ACTIVATION_ATOM_MATCHER_INDEX, atom_matcher_index); if (ActivationState::kActive == activation->state) { const int64_t remainingTtlNs = activation->start_ns + activation->ttl_ns - currentTimeNs; proto->write(FIELD_TYPE_INT64 | FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS, (long long)remainingTtlNs); } else if (ActivationState::kActiveOnBoot == activation->state) { proto->write(FIELD_TYPE_INT64 | FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS, (long long)activation->ttl_ns); } proto->end(activationToken); } } Loading