Loading cmds/statsd/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ statsd_common_src := \ src/packages/UidMap.cpp \ src/storage/DropboxReader.cpp \ src/storage/DropboxWriter.cpp \ src/storage/StorageManager.cpp \ src/StatsLogProcessor.cpp \ src/StatsService.cpp \ src/stats_util.cpp \ Loading cmds/statsd/src/StatsLogProcessor.cpp +43 −5 Original line number Diff line number Diff line Loading @@ -17,14 +17,19 @@ #include "Log.h" #include "statslog.h" #include <android-base/file.h> #include <dirent.h> #include "StatsLogProcessor.h" #include "android-base/stringprintf.h" #include "metrics/CountMetricProducer.h" #include "stats_util.h" #include "storage/StorageManager.h" #include <log/log_event_list.h> #include <utils/Errors.h> using namespace android; using android::base::StringPrintf; using android::util::FIELD_COUNT_REPEATED; using android::util::FIELD_TYPE_BOOL; using android::util::FIELD_TYPE_FLOAT; Loading @@ -41,18 +46,25 @@ namespace android { namespace os { namespace statsd { // for ConfigMetricsReport // for ConfigMetricsReportList const int FIELD_ID_CONFIG_KEY = 1; const int FIELD_ID_METRICS = 2; const int FIELD_ID_UID_MAP = 3; const int FIELD_ID_REPORTS = 2; // for ConfigKey const int FIELD_ID_UID = 1; const int FIELD_ID_NAME = 2; // for ConfigMetricsReport const int FIELD_ID_METRICS = 1; const int FIELD_ID_UID_MAP = 2; #define STATS_DATA_DIR "/data/system/stats-data" StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap, const sp<AnomalyMonitor>& anomalyMonitor, const std::function<void(const ConfigKey&)>& sendBroadcast) : mUidMap(uidMap), mAnomalyMonitor(anomalyMonitor), mSendBroadcast(sendBroadcast) { // On each initialization of StatsLogProcessor, check stats-data directory to see if there is // any left over data to be read. StorageManager::sendBroadcast(STATS_DATA_DIR, mSendBroadcast); } StatsLogProcessor::~StatsLogProcessor() { Loading Loading @@ -138,13 +150,19 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, vector<uint8_t>* outD ProtoOutputStream proto; // Fill in ConfigKey. // Start of ConfigKey. long long configKeyToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_KEY); proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID, key.GetUid()); proto.write(FIELD_TYPE_STRING | FIELD_ID_NAME, key.GetName()); proto.end(configKeyToken); // End of ConfigKey. // Fill in StatsLogReport's. // Start of ConfigMetricsReport (reports). long long reportsToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS); // First, fill in ConfigMetricsReport using current data on memory, which // starts from filling in StatsLogReport's. for (auto& m : it->second->onDumpReport()) { // Add each vector of StatsLogReport into a repeated field. proto.write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_METRICS, Loading @@ -158,6 +176,13 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, vector<uint8_t>* outD uidMap.SerializeToArray(&uidMapBuffer[0], uidMapSize); proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP, uidMapBuffer, uidMapSize); // End of ConfigMetricsReport (reports). proto.end(reportsToken); // Then, check stats-data directory to see there's any file containing // ConfigMetricsReport from previous shutdowns to concatenate to reports. StorageManager::appendConfigMetricsReport(STATS_DATA_DIR, proto); if (outData != nullptr) { outData->clear(); outData->resize(proto.size()); Loading Loading @@ -207,6 +232,19 @@ void StatsLogProcessor::flushIfNecessary(uint64_t timestampNs, } } void StatsLogProcessor::WriteDataToDisk() { mkdir(STATS_DATA_DIR, S_IRWXU); for (auto& pair : mMetricsManagers) { const ConfigKey& key = pair.first; vector<uint8_t> data; onDumpReport(key, &data); // TODO: Add a guardrail to prevent accumulation of file on disk. string file_name = StringPrintf("%s/%d-%s-%ld", STATS_DATA_DIR, key.GetUid(), key.GetName().c_str(), time(nullptr)); StorageManager::writeFile(file_name.c_str(), &data[0], data.size()); } } } // namespace statsd } // namespace os } // namespace android cmds/statsd/src/StatsLogProcessor.h +3 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,9 @@ public: const uint64_t timestampNs, unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> anomalySet); /* Flushes data to disk. Data on memory will be gone after written to disk. */ void WriteDataToDisk(); private: mutable mutex mBroadcastTimesMutex; Loading cmds/statsd/src/StatsService.cpp +31 −17 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include "config/ConfigManager.h" #include "guardrail/MemoryLeakTrackUtil.h" #include "storage/DropboxReader.h" #include "storage/StorageManager.h" #include <android-base/file.h> #include <binder/IPCThreadState.h> Loading Loading @@ -75,7 +76,7 @@ StatsService::StatsService(const sp<Looper>& handlerLooper) mUidMap = new UidMap(); mConfigManager = new ConfigManager(); mProcessor = new StatsLogProcessor(mUidMap, mAnomalyMonitor, [this](const ConfigKey& key) { auto sc = getStatsCompanionService(); sp<IStatsCompanionService> sc = getStatsCompanionService(); auto receiver = mConfigManager->GetConfigReceiver(key); if (sc == nullptr) { ALOGD("Could not find StatsCompanionService"); Loading Loading @@ -231,6 +232,10 @@ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& if (!args[0].compare(String8("meminfo"))) { return cmd_dump_memory_info(out); } if (!args[0].compare(String8("write-to-disk"))) { return cmd_write_data_to_disk(out); } } print_cmd_help(out); Loading Loading @@ -267,6 +272,11 @@ void StatsService::print_cmd_help(FILE* out) { fprintf(out, " Prints the output of a pulled metrics source (int indicates source)\n"); fprintf(out, "\n"); fprintf(out, "\n"); fprintf(out, "usage: adb shell cmd stats write-to-disk \n"); fprintf(out, "\n"); fprintf(out, " Flushes all data on memory to disk.\n"); fprintf(out, "\n"); fprintf(out, "\n"); fprintf(out, "usage: adb shell cmd stats config remove [UID] NAME\n"); fprintf(out, "usage: adb shell cmd stats config update [UID] NAME\n"); fprintf(out, "\n"); Loading Loading @@ -487,6 +497,12 @@ status_t StatsService::cmd_print_uid_map(FILE* out) { return NO_ERROR; } status_t StatsService::cmd_write_data_to_disk(FILE* out) { fprintf(out, "Writing data to disk\n"); mProcessor->WriteDataToDisk(); return NO_ERROR; } status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8>& args) { int s = atoi(args[1].c_str()); vector<shared_ptr<LogEvent> > stats; Loading @@ -502,22 +518,7 @@ status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8> status_t StatsService::cmd_remove_config_files(FILE* out) { fprintf(out, "Trying to remove config files...\n"); unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir); if (dir == NULL) { fprintf(out, "No existing config files found exiting...\n"); return NO_ERROR; } dirent* de; while ((de = readdir(dir.get()))) { char* name = de->d_name; if (name[0] == '.') continue; string file_name = StringPrintf("%s/%s", STATS_SERVICE_DIR, name); fprintf(out, "Deleting file %s\n", file_name.c_str()); if (remove(file_name.c_str())) { fprintf(out, "Error deleting file %s\n", file_name.c_str()); } } StorageManager::deleteAllFiles(STATS_SERVICE_DIR); return NO_ERROR; } Loading Loading @@ -611,6 +612,19 @@ Status StatsService::systemRunning() { return Status::ok(); } Status StatsService::writeDataToDisk() { if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call systemRunning"); } ALOGD("StatsService::writeDataToDisk"); mProcessor->WriteDataToDisk(); return Status::ok(); } void StatsService::sayHiToStatsCompanion() { // TODO: This method needs to be private. It is temporarily public and unsecured for testing // purposes. Loading cmds/statsd/src/StatsService.h +6 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ public: const vector<String16>& app); virtual Status informOnePackage(const String16& app, int32_t uid, int32_t version); virtual Status informOnePackageRemoved(const String16& app, int32_t uid); virtual Status writeDataToDisk(); /** * Called right before we start processing events. Loading Loading @@ -150,6 +151,11 @@ private: */ status_t cmd_print_uid_map(FILE* out); /** * Flush the data to disk. */ status_t cmd_write_data_to_disk(FILE* out); /** * Print contents of a pulled metrics source. */ Loading Loading
cmds/statsd/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ statsd_common_src := \ src/packages/UidMap.cpp \ src/storage/DropboxReader.cpp \ src/storage/DropboxWriter.cpp \ src/storage/StorageManager.cpp \ src/StatsLogProcessor.cpp \ src/StatsService.cpp \ src/stats_util.cpp \ Loading
cmds/statsd/src/StatsLogProcessor.cpp +43 −5 Original line number Diff line number Diff line Loading @@ -17,14 +17,19 @@ #include "Log.h" #include "statslog.h" #include <android-base/file.h> #include <dirent.h> #include "StatsLogProcessor.h" #include "android-base/stringprintf.h" #include "metrics/CountMetricProducer.h" #include "stats_util.h" #include "storage/StorageManager.h" #include <log/log_event_list.h> #include <utils/Errors.h> using namespace android; using android::base::StringPrintf; using android::util::FIELD_COUNT_REPEATED; using android::util::FIELD_TYPE_BOOL; using android::util::FIELD_TYPE_FLOAT; Loading @@ -41,18 +46,25 @@ namespace android { namespace os { namespace statsd { // for ConfigMetricsReport // for ConfigMetricsReportList const int FIELD_ID_CONFIG_KEY = 1; const int FIELD_ID_METRICS = 2; const int FIELD_ID_UID_MAP = 3; const int FIELD_ID_REPORTS = 2; // for ConfigKey const int FIELD_ID_UID = 1; const int FIELD_ID_NAME = 2; // for ConfigMetricsReport const int FIELD_ID_METRICS = 1; const int FIELD_ID_UID_MAP = 2; #define STATS_DATA_DIR "/data/system/stats-data" StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap, const sp<AnomalyMonitor>& anomalyMonitor, const std::function<void(const ConfigKey&)>& sendBroadcast) : mUidMap(uidMap), mAnomalyMonitor(anomalyMonitor), mSendBroadcast(sendBroadcast) { // On each initialization of StatsLogProcessor, check stats-data directory to see if there is // any left over data to be read. StorageManager::sendBroadcast(STATS_DATA_DIR, mSendBroadcast); } StatsLogProcessor::~StatsLogProcessor() { Loading Loading @@ -138,13 +150,19 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, vector<uint8_t>* outD ProtoOutputStream proto; // Fill in ConfigKey. // Start of ConfigKey. long long configKeyToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_KEY); proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID, key.GetUid()); proto.write(FIELD_TYPE_STRING | FIELD_ID_NAME, key.GetName()); proto.end(configKeyToken); // End of ConfigKey. // Fill in StatsLogReport's. // Start of ConfigMetricsReport (reports). long long reportsToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS); // First, fill in ConfigMetricsReport using current data on memory, which // starts from filling in StatsLogReport's. for (auto& m : it->second->onDumpReport()) { // Add each vector of StatsLogReport into a repeated field. proto.write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_METRICS, Loading @@ -158,6 +176,13 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, vector<uint8_t>* outD uidMap.SerializeToArray(&uidMapBuffer[0], uidMapSize); proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP, uidMapBuffer, uidMapSize); // End of ConfigMetricsReport (reports). proto.end(reportsToken); // Then, check stats-data directory to see there's any file containing // ConfigMetricsReport from previous shutdowns to concatenate to reports. StorageManager::appendConfigMetricsReport(STATS_DATA_DIR, proto); if (outData != nullptr) { outData->clear(); outData->resize(proto.size()); Loading Loading @@ -207,6 +232,19 @@ void StatsLogProcessor::flushIfNecessary(uint64_t timestampNs, } } void StatsLogProcessor::WriteDataToDisk() { mkdir(STATS_DATA_DIR, S_IRWXU); for (auto& pair : mMetricsManagers) { const ConfigKey& key = pair.first; vector<uint8_t> data; onDumpReport(key, &data); // TODO: Add a guardrail to prevent accumulation of file on disk. string file_name = StringPrintf("%s/%d-%s-%ld", STATS_DATA_DIR, key.GetUid(), key.GetName().c_str(), time(nullptr)); StorageManager::writeFile(file_name.c_str(), &data[0], data.size()); } } } // namespace statsd } // namespace os } // namespace android
cmds/statsd/src/StatsLogProcessor.h +3 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,9 @@ public: const uint64_t timestampNs, unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> anomalySet); /* Flushes data to disk. Data on memory will be gone after written to disk. */ void WriteDataToDisk(); private: mutable mutex mBroadcastTimesMutex; Loading
cmds/statsd/src/StatsService.cpp +31 −17 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include "config/ConfigManager.h" #include "guardrail/MemoryLeakTrackUtil.h" #include "storage/DropboxReader.h" #include "storage/StorageManager.h" #include <android-base/file.h> #include <binder/IPCThreadState.h> Loading Loading @@ -75,7 +76,7 @@ StatsService::StatsService(const sp<Looper>& handlerLooper) mUidMap = new UidMap(); mConfigManager = new ConfigManager(); mProcessor = new StatsLogProcessor(mUidMap, mAnomalyMonitor, [this](const ConfigKey& key) { auto sc = getStatsCompanionService(); sp<IStatsCompanionService> sc = getStatsCompanionService(); auto receiver = mConfigManager->GetConfigReceiver(key); if (sc == nullptr) { ALOGD("Could not find StatsCompanionService"); Loading Loading @@ -231,6 +232,10 @@ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& if (!args[0].compare(String8("meminfo"))) { return cmd_dump_memory_info(out); } if (!args[0].compare(String8("write-to-disk"))) { return cmd_write_data_to_disk(out); } } print_cmd_help(out); Loading Loading @@ -267,6 +272,11 @@ void StatsService::print_cmd_help(FILE* out) { fprintf(out, " Prints the output of a pulled metrics source (int indicates source)\n"); fprintf(out, "\n"); fprintf(out, "\n"); fprintf(out, "usage: adb shell cmd stats write-to-disk \n"); fprintf(out, "\n"); fprintf(out, " Flushes all data on memory to disk.\n"); fprintf(out, "\n"); fprintf(out, "\n"); fprintf(out, "usage: adb shell cmd stats config remove [UID] NAME\n"); fprintf(out, "usage: adb shell cmd stats config update [UID] NAME\n"); fprintf(out, "\n"); Loading Loading @@ -487,6 +497,12 @@ status_t StatsService::cmd_print_uid_map(FILE* out) { return NO_ERROR; } status_t StatsService::cmd_write_data_to_disk(FILE* out) { fprintf(out, "Writing data to disk\n"); mProcessor->WriteDataToDisk(); return NO_ERROR; } status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8>& args) { int s = atoi(args[1].c_str()); vector<shared_ptr<LogEvent> > stats; Loading @@ -502,22 +518,7 @@ status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8> status_t StatsService::cmd_remove_config_files(FILE* out) { fprintf(out, "Trying to remove config files...\n"); unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir); if (dir == NULL) { fprintf(out, "No existing config files found exiting...\n"); return NO_ERROR; } dirent* de; while ((de = readdir(dir.get()))) { char* name = de->d_name; if (name[0] == '.') continue; string file_name = StringPrintf("%s/%s", STATS_SERVICE_DIR, name); fprintf(out, "Deleting file %s\n", file_name.c_str()); if (remove(file_name.c_str())) { fprintf(out, "Error deleting file %s\n", file_name.c_str()); } } StorageManager::deleteAllFiles(STATS_SERVICE_DIR); return NO_ERROR; } Loading Loading @@ -611,6 +612,19 @@ Status StatsService::systemRunning() { return Status::ok(); } Status StatsService::writeDataToDisk() { if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call systemRunning"); } ALOGD("StatsService::writeDataToDisk"); mProcessor->WriteDataToDisk(); return Status::ok(); } void StatsService::sayHiToStatsCompanion() { // TODO: This method needs to be private. It is temporarily public and unsecured for testing // purposes. Loading
cmds/statsd/src/StatsService.h +6 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ public: const vector<String16>& app); virtual Status informOnePackage(const String16& app, int32_t uid, int32_t version); virtual Status informOnePackageRemoved(const String16& app, int32_t uid); virtual Status writeDataToDisk(); /** * Called right before we start processing events. Loading Loading @@ -150,6 +151,11 @@ private: */ status_t cmd_print_uid_map(FILE* out); /** * Flush the data to disk. */ status_t cmd_write_data_to_disk(FILE* out); /** * Print contents of a pulled metrics source. */ Loading