Loading cmds/statsd/Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ cc_defaults { srcs: [ ":statsd_aidl", "src/active_config_list.proto", "src/statsd_config.proto", "src/FieldValue.cpp", "src/hash.cpp", Loading cmds/statsd/src/StatsLogProcessor.cpp +76 −3 Original line number Diff line number Diff line Loading @@ -20,12 +20,13 @@ #include <android-base/file.h> #include <dirent.h> #include <frameworks/base/cmds/statsd/src/active_config_list.pb.h> #include "StatsLogProcessor.h" #include "stats_log_util.h" #include "android-base/stringprintf.h" #include "external/StatsPullerManager.h" #include "guardrail/StatsdStats.h" #include "metrics/CountMetricProducer.h" #include "external/StatsPullerManager.h" #include "stats_log_util.h" #include "stats_util.h" #include "storage/StorageManager.h" Loading Loading @@ -67,9 +68,17 @@ 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; #define NS_PER_HOUR 3600 * NS_PER_SEC #define STATS_DATA_DIR "/data/misc/stats-data" #define STATS_ACTIVE_METRIC_DIR "/data/misc/stats-active-metric" // Cool down period for writing data to disk to avoid overwriting files. #define WRITE_DATA_COOL_DOWN_SEC 5 Loading Loading @@ -507,6 +516,70 @@ void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key, mOnDiskDataConfigs.insert(key); } void StatsLogProcessor::WriteMetricsActivationToDisk(int64_t currentTimeNs) { std::lock_guard<std::mutex> lock(mMetricsMutex); 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<const MetricProducer*> acrtiveMetrics; pair.second->getActiveMetrics(acrtiveMetrics); for (const MetricProducer* metric : acrtiveMetrics) { 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); } string file_name = StringPrintf("%s/active_metrics", STATS_ACTIVE_METRIC_DIR); StorageManager::deleteFile(file_name.c_str()); android::base::unique_fd fd( open(file_name.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR)); if (fd == -1) { ALOGE("Attempt to write %s but failed", file_name.c_str()); return; } proto.flush(fd.get()); } void StatsLogProcessor::LoadMetricsActivationFromDisk() { 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) { string content; if (android::base::ReadFdToString(fd, &content)) { 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()); 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); } StorageManager::deleteFile(file_name.c_str()); } void StatsLogProcessor::WriteDataToDiskLocked(const DumpReportReason dumpReportReason) { const int64_t timeNs = getElapsedRealtimeNs(); // Do not write to disk if we already have in the last few seconds. Loading cmds/statsd/src/StatsLogProcessor.h +8 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,12 @@ public: /* Flushes data to disk. Data on memory will be gone after written to disk. */ void WriteDataToDisk(const DumpReportReason dumpReportReason); /* Persist metric activation status onto disk. */ void WriteMetricsActivationToDisk(int64_t currentTimeNs); /* Load metric activation status from disk. */ void LoadMetricsActivationFromDisk(); // Reset all configs. void resetConfigs(); Loading Loading @@ -188,6 +194,8 @@ private: FRIEND_TEST(StatsLogProcessorTest, TestRateLimitByteSize); FRIEND_TEST(StatsLogProcessorTest, TestRateLimitBroadcast); FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge); FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead); FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1); FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2); FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3); Loading cmds/statsd/src/StatsService.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -161,7 +161,8 @@ StatsService::StatsService(const sp<Looper>& handlerLooper) mConfigManager = new ConfigManager(); mProcessor = new StatsLogProcessor( mUidMap, mPullerManager, mAnomalyAlarmMonitor, mPeriodicAlarmMonitor, getElapsedRealtimeNs(), [this](const ConfigKey& key) { getElapsedRealtimeNs(), [this](const ConfigKey& key) { sp<IStatsCompanionService> sc = getStatsCompanionService(); auto receiver = mConfigManager->GetConfigReceiver(key); if (sc == nullptr) { Loading Loading @@ -867,6 +868,7 @@ Status StatsService::informDeviceShutdown() { ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informDeviceShutdown"); mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN); mProcessor->WriteMetricsActivationToDisk(getElapsedRealtimeNs()); return Status::ok(); } Loading Loading @@ -901,6 +903,7 @@ Status StatsService::statsCompanionReady() { void StatsService::Startup() { mConfigManager->Startup(); mProcessor->LoadMetricsActivationFromDisk(); } void StatsService::Terminate() { Loading cmds/statsd/src/active_config_list.proto 0 → 100644 +43 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ syntax = "proto2"; package android.os.statsd; option java_package = "com.android.os"; option java_multiple_files = true; option java_outer_classname = "ActiveConfigProto"; 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; } message ActiveConfig { // config id optional int64 config_id = 1; // config uid optional int32 uid = 2; // metrics repeated ActiveMetric active_metric = 3; } // all configs and their metrics on device. message ActiveConfigList { repeated ActiveConfig active_config = 1; } No newline at end of file Loading
cmds/statsd/Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ cc_defaults { srcs: [ ":statsd_aidl", "src/active_config_list.proto", "src/statsd_config.proto", "src/FieldValue.cpp", "src/hash.cpp", Loading
cmds/statsd/src/StatsLogProcessor.cpp +76 −3 Original line number Diff line number Diff line Loading @@ -20,12 +20,13 @@ #include <android-base/file.h> #include <dirent.h> #include <frameworks/base/cmds/statsd/src/active_config_list.pb.h> #include "StatsLogProcessor.h" #include "stats_log_util.h" #include "android-base/stringprintf.h" #include "external/StatsPullerManager.h" #include "guardrail/StatsdStats.h" #include "metrics/CountMetricProducer.h" #include "external/StatsPullerManager.h" #include "stats_log_util.h" #include "stats_util.h" #include "storage/StorageManager.h" Loading Loading @@ -67,9 +68,17 @@ 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; #define NS_PER_HOUR 3600 * NS_PER_SEC #define STATS_DATA_DIR "/data/misc/stats-data" #define STATS_ACTIVE_METRIC_DIR "/data/misc/stats-active-metric" // Cool down period for writing data to disk to avoid overwriting files. #define WRITE_DATA_COOL_DOWN_SEC 5 Loading Loading @@ -507,6 +516,70 @@ void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key, mOnDiskDataConfigs.insert(key); } void StatsLogProcessor::WriteMetricsActivationToDisk(int64_t currentTimeNs) { std::lock_guard<std::mutex> lock(mMetricsMutex); 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<const MetricProducer*> acrtiveMetrics; pair.second->getActiveMetrics(acrtiveMetrics); for (const MetricProducer* metric : acrtiveMetrics) { 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); } string file_name = StringPrintf("%s/active_metrics", STATS_ACTIVE_METRIC_DIR); StorageManager::deleteFile(file_name.c_str()); android::base::unique_fd fd( open(file_name.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR)); if (fd == -1) { ALOGE("Attempt to write %s but failed", file_name.c_str()); return; } proto.flush(fd.get()); } void StatsLogProcessor::LoadMetricsActivationFromDisk() { 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) { string content; if (android::base::ReadFdToString(fd, &content)) { 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()); 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); } StorageManager::deleteFile(file_name.c_str()); } void StatsLogProcessor::WriteDataToDiskLocked(const DumpReportReason dumpReportReason) { const int64_t timeNs = getElapsedRealtimeNs(); // Do not write to disk if we already have in the last few seconds. Loading
cmds/statsd/src/StatsLogProcessor.h +8 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,12 @@ public: /* Flushes data to disk. Data on memory will be gone after written to disk. */ void WriteDataToDisk(const DumpReportReason dumpReportReason); /* Persist metric activation status onto disk. */ void WriteMetricsActivationToDisk(int64_t currentTimeNs); /* Load metric activation status from disk. */ void LoadMetricsActivationFromDisk(); // Reset all configs. void resetConfigs(); Loading Loading @@ -188,6 +194,8 @@ private: FRIEND_TEST(StatsLogProcessorTest, TestRateLimitByteSize); FRIEND_TEST(StatsLogProcessorTest, TestRateLimitBroadcast); FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge); FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead); FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1); FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2); FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3); Loading
cmds/statsd/src/StatsService.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -161,7 +161,8 @@ StatsService::StatsService(const sp<Looper>& handlerLooper) mConfigManager = new ConfigManager(); mProcessor = new StatsLogProcessor( mUidMap, mPullerManager, mAnomalyAlarmMonitor, mPeriodicAlarmMonitor, getElapsedRealtimeNs(), [this](const ConfigKey& key) { getElapsedRealtimeNs(), [this](const ConfigKey& key) { sp<IStatsCompanionService> sc = getStatsCompanionService(); auto receiver = mConfigManager->GetConfigReceiver(key); if (sc == nullptr) { Loading Loading @@ -867,6 +868,7 @@ Status StatsService::informDeviceShutdown() { ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informDeviceShutdown"); mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN); mProcessor->WriteMetricsActivationToDisk(getElapsedRealtimeNs()); return Status::ok(); } Loading Loading @@ -901,6 +903,7 @@ Status StatsService::statsCompanionReady() { void StatsService::Startup() { mConfigManager->Startup(); mProcessor->LoadMetricsActivationFromDisk(); } void StatsService::Terminate() { Loading
cmds/statsd/src/active_config_list.proto 0 → 100644 +43 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ syntax = "proto2"; package android.os.statsd; option java_package = "com.android.os"; option java_multiple_files = true; option java_outer_classname = "ActiveConfigProto"; 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; } message ActiveConfig { // config id optional int64 config_id = 1; // config uid optional int32 uid = 2; // metrics repeated ActiveMetric active_metric = 3; } // all configs and their metrics on device. message ActiveConfigList { repeated ActiveConfig active_config = 1; } No newline at end of file