Loading cmds/statsd/src/StatsService.cpp +33 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #define DEBUG true #include "Log.h" #include "android-base/stringprintf.h" #include "StatsService.h" #include "config/ConfigKey.h" #include "config/ConfigManager.h" Loading @@ -25,11 +26,11 @@ #include <android-base/file.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <dirent.h> #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h> #include <private/android_filesystem_config.h> #include <utils/Looper.h> #include <utils/String16.h> #include <stdio.h> #include <stdlib.h> #include <sys/system_properties.h> Loading @@ -42,6 +43,7 @@ namespace os { namespace statsd { constexpr const char* kPermissionDump = "android.permission.DUMP"; #define STATS_SERVICE_DIR "/data/system/stats-service" // ====================================================================== /** Loading Loading @@ -206,6 +208,10 @@ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& if (!args[0].compare(String8("send-broadcast"))) { return cmd_trigger_broadcast(args); } if (!args[0].compare(String8("clear-config"))) { return cmd_remove_config_files(out); } } print_cmd_help(out); Loading @@ -223,6 +229,11 @@ void StatsService::print_cmd_help(FILE* out) { fprintf(out, " Prints the UID, app name, version mapping.\n"); fprintf(out, "\n"); fprintf(out, "\n"); fprintf(out, "usage: adb shell cmd stats clear-config \n"); fprintf(out, "\n"); fprintf(out, " Removes all configs from disk.\n"); fprintf(out, "\n"); fprintf(out, "\n"); fprintf(out, "usage: adb shell cmds stats pull-source [int] \n"); fprintf(out, "\n"); fprintf(out, " Prints the output of a pulled metrics source (int indicates source)\n"); Loading Loading @@ -405,6 +416,27 @@ status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8> return UNKNOWN_ERROR; } 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()); } } return NO_ERROR; } Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int32_t>& version, const vector<String16>& app) { if (DEBUG) ALOGD("StatsService::informAllUidData was called"); Loading cmds/statsd/src/StatsService.h +5 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,11 @@ private: */ status_t cmd_print_pulled_metrics(FILE* out, const Vector<String8>& args); /** * Removes all configs stored on disk. */ status_t cmd_remove_config_files(FILE* out); /** * Update a configuration. */ Loading cmds/statsd/src/config/ConfigKey.h +1 −1 Original line number Diff line number Diff line Loading @@ -78,7 +78,7 @@ inline ostream& operator<<(ostream& os, const ConfigKey& config) { /** * A hash function for ConfigKey so it can be used for unordered_map/set. * Unfortunately this hast to go in std namespace because C++ is fun! * Unfortunately this has to go in std namespace because C++ is fun! */ namespace std { Loading cmds/statsd/src/config/ConfigManager.cpp +91 −9 Original line number Diff line number Diff line Loading @@ -18,16 +18,23 @@ #include "stats_util.h" #include <vector> #include <android-base/file.h> #include <dirent.h> #include <stdio.h> #include <vector> #include "android-base/stringprintf.h" namespace android { namespace os { namespace statsd { #define STATS_SERVICE_DIR "/data/system/stats-service" static StatsdConfig build_fake_config(); using android::base::StringPrintf; using std::unique_ptr; ConfigManager::ConfigManager() { } Loading @@ -35,8 +42,7 @@ ConfigManager::~ConfigManager() { } void ConfigManager::Startup() { // TODO: Implement me -- read from storage and call onto all of the listeners. // Instead, we'll just make a fake one. readConfigFromDisk(); // this should be called from StatsService when it receives a statsd_config UpdateConfig(ConfigKey(0, "fake"), build_fake_config()); Loading @@ -52,7 +58,7 @@ void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& confi // Why doesn't this work? mConfigs.insert({key, config}); // Save to disk update_saved_configs(); update_saved_configs(key, config); // Tell everyone for (auto& listener : mListeners) { Loading @@ -74,8 +80,8 @@ void ConfigManager::RemoveConfig(const ConfigKey& key) { // Remove from map mConfigs.erase(it); // Save to disk update_saved_configs(); // Remove from disk remove_saved_configs(key); // Tell everyone for (auto& listener : mListeners) { Loading @@ -85,6 +91,26 @@ void ConfigManager::RemoveConfig(const ConfigKey& key) { // If we didn't find it, just quietly ignore it. } void ConfigManager::remove_saved_configs(const ConfigKey& key) { unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir); if (dir == NULL) { ALOGD("no default config on disk"); return; } string prefix = StringPrintf("%d-%s", key.GetUid(), key.GetName().c_str()); dirent* de; while ((de = readdir(dir.get()))) { char* name = de->d_name; if (name[0] != '.' && strncmp(name, prefix.c_str(), prefix.size()) == 0) { if (remove(StringPrintf("%s/%d-%s", STATS_SERVICE_DIR, key.GetUid(), key.GetName().c_str()) .c_str()) != 0) { ALOGD("no file found"); } } } } void ConfigManager::RemoveConfigs(int uid) { vector<ConfigKey> removed; Loading Loading @@ -118,8 +144,64 @@ void ConfigManager::Dump(FILE* out) { } } void ConfigManager::update_saved_configs() { // TODO: Implement me -- write to disk. void ConfigManager::readConfigFromDisk() { unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir); if (dir == NULL) { ALOGD("no default config on disk"); return; } dirent* de; while ((de = readdir(dir.get()))) { char* name = de->d_name; if (name[0] == '.') continue; ALOGD("file %s", name); int index = 0; int uid = 0; string configName; char* substr = strtok(name, "-"); // Timestamp lives at index 2 but we skip parsing it as it's not needed. while (substr != nullptr && index < 2) { if (index) { uid = atoi(substr); } else { configName = substr; } index++; } if (index < 2) continue; string file_name = StringPrintf("%s/%s", STATS_SERVICE_DIR, name); ALOGD("full file %s", file_name.c_str()); int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC); if (fd != -1) { string content; if (android::base::ReadFdToString(fd, &content)) { StatsdConfig config; if (config.ParseFromString(content)) { mConfigs[ConfigKey(uid, configName)] = config; ALOGD("map key uid=%d|name=%s", uid, name); } } close(fd); } } } void ConfigManager::update_saved_configs(const ConfigKey& key, const StatsdConfig& config) { mkdir(STATS_SERVICE_DIR, S_IRWXU); string file_name = StringPrintf("%s/%d-%s-%ld", STATS_SERVICE_DIR, key.GetUid(), key.GetName().c_str(), time(nullptr)); int fd = open(file_name.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR); if (fd != -1) { const int numBytes = config.ByteSize(); vector<uint8_t> buffer(numBytes); config.SerializeToArray(&buffer[0], numBytes); int result = write(fd, &buffer[0], numBytes); close(fd); bool wroteKey = (result == numBytes); ALOGD("wrote to file %d", wroteKey); } } static StatsdConfig build_fake_config() { Loading cmds/statsd/src/config/ConfigManager.h +12 −4 Original line number Diff line number Diff line Loading @@ -46,9 +46,7 @@ public: virtual ~ConfigManager(); /** * Call to load the saved configs from disk. * * TODO: Implement me * Initialize ConfigListener by reading from disk and get updates. */ void Startup(); Loading Loading @@ -95,7 +93,12 @@ private: /** * Save the configs to disk. */ void update_saved_configs(); void update_saved_configs(const ConfigKey& key, const StatsdConfig& config); /** * Remove saved configs from disk. */ void remove_saved_configs(const ConfigKey& key); /** * The Configs that have been set. Each config should Loading @@ -112,6 +115,11 @@ private: * The ConfigListeners that will be told about changes. */ vector<sp<ConfigListener>> mListeners; /** * Call to load the saved configs from disk. */ void readConfigFromDisk(); }; } // namespace statsd Loading Loading
cmds/statsd/src/StatsService.cpp +33 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #define DEBUG true #include "Log.h" #include "android-base/stringprintf.h" #include "StatsService.h" #include "config/ConfigKey.h" #include "config/ConfigManager.h" Loading @@ -25,11 +26,11 @@ #include <android-base/file.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <dirent.h> #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h> #include <private/android_filesystem_config.h> #include <utils/Looper.h> #include <utils/String16.h> #include <stdio.h> #include <stdlib.h> #include <sys/system_properties.h> Loading @@ -42,6 +43,7 @@ namespace os { namespace statsd { constexpr const char* kPermissionDump = "android.permission.DUMP"; #define STATS_SERVICE_DIR "/data/system/stats-service" // ====================================================================== /** Loading Loading @@ -206,6 +208,10 @@ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& if (!args[0].compare(String8("send-broadcast"))) { return cmd_trigger_broadcast(args); } if (!args[0].compare(String8("clear-config"))) { return cmd_remove_config_files(out); } } print_cmd_help(out); Loading @@ -223,6 +229,11 @@ void StatsService::print_cmd_help(FILE* out) { fprintf(out, " Prints the UID, app name, version mapping.\n"); fprintf(out, "\n"); fprintf(out, "\n"); fprintf(out, "usage: adb shell cmd stats clear-config \n"); fprintf(out, "\n"); fprintf(out, " Removes all configs from disk.\n"); fprintf(out, "\n"); fprintf(out, "\n"); fprintf(out, "usage: adb shell cmds stats pull-source [int] \n"); fprintf(out, "\n"); fprintf(out, " Prints the output of a pulled metrics source (int indicates source)\n"); Loading Loading @@ -405,6 +416,27 @@ status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8> return UNKNOWN_ERROR; } 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()); } } return NO_ERROR; } Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int32_t>& version, const vector<String16>& app) { if (DEBUG) ALOGD("StatsService::informAllUidData was called"); Loading
cmds/statsd/src/StatsService.h +5 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,11 @@ private: */ status_t cmd_print_pulled_metrics(FILE* out, const Vector<String8>& args); /** * Removes all configs stored on disk. */ status_t cmd_remove_config_files(FILE* out); /** * Update a configuration. */ Loading
cmds/statsd/src/config/ConfigKey.h +1 −1 Original line number Diff line number Diff line Loading @@ -78,7 +78,7 @@ inline ostream& operator<<(ostream& os, const ConfigKey& config) { /** * A hash function for ConfigKey so it can be used for unordered_map/set. * Unfortunately this hast to go in std namespace because C++ is fun! * Unfortunately this has to go in std namespace because C++ is fun! */ namespace std { Loading
cmds/statsd/src/config/ConfigManager.cpp +91 −9 Original line number Diff line number Diff line Loading @@ -18,16 +18,23 @@ #include "stats_util.h" #include <vector> #include <android-base/file.h> #include <dirent.h> #include <stdio.h> #include <vector> #include "android-base/stringprintf.h" namespace android { namespace os { namespace statsd { #define STATS_SERVICE_DIR "/data/system/stats-service" static StatsdConfig build_fake_config(); using android::base::StringPrintf; using std::unique_ptr; ConfigManager::ConfigManager() { } Loading @@ -35,8 +42,7 @@ ConfigManager::~ConfigManager() { } void ConfigManager::Startup() { // TODO: Implement me -- read from storage and call onto all of the listeners. // Instead, we'll just make a fake one. readConfigFromDisk(); // this should be called from StatsService when it receives a statsd_config UpdateConfig(ConfigKey(0, "fake"), build_fake_config()); Loading @@ -52,7 +58,7 @@ void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& confi // Why doesn't this work? mConfigs.insert({key, config}); // Save to disk update_saved_configs(); update_saved_configs(key, config); // Tell everyone for (auto& listener : mListeners) { Loading @@ -74,8 +80,8 @@ void ConfigManager::RemoveConfig(const ConfigKey& key) { // Remove from map mConfigs.erase(it); // Save to disk update_saved_configs(); // Remove from disk remove_saved_configs(key); // Tell everyone for (auto& listener : mListeners) { Loading @@ -85,6 +91,26 @@ void ConfigManager::RemoveConfig(const ConfigKey& key) { // If we didn't find it, just quietly ignore it. } void ConfigManager::remove_saved_configs(const ConfigKey& key) { unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir); if (dir == NULL) { ALOGD("no default config on disk"); return; } string prefix = StringPrintf("%d-%s", key.GetUid(), key.GetName().c_str()); dirent* de; while ((de = readdir(dir.get()))) { char* name = de->d_name; if (name[0] != '.' && strncmp(name, prefix.c_str(), prefix.size()) == 0) { if (remove(StringPrintf("%s/%d-%s", STATS_SERVICE_DIR, key.GetUid(), key.GetName().c_str()) .c_str()) != 0) { ALOGD("no file found"); } } } } void ConfigManager::RemoveConfigs(int uid) { vector<ConfigKey> removed; Loading Loading @@ -118,8 +144,64 @@ void ConfigManager::Dump(FILE* out) { } } void ConfigManager::update_saved_configs() { // TODO: Implement me -- write to disk. void ConfigManager::readConfigFromDisk() { unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir); if (dir == NULL) { ALOGD("no default config on disk"); return; } dirent* de; while ((de = readdir(dir.get()))) { char* name = de->d_name; if (name[0] == '.') continue; ALOGD("file %s", name); int index = 0; int uid = 0; string configName; char* substr = strtok(name, "-"); // Timestamp lives at index 2 but we skip parsing it as it's not needed. while (substr != nullptr && index < 2) { if (index) { uid = atoi(substr); } else { configName = substr; } index++; } if (index < 2) continue; string file_name = StringPrintf("%s/%s", STATS_SERVICE_DIR, name); ALOGD("full file %s", file_name.c_str()); int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC); if (fd != -1) { string content; if (android::base::ReadFdToString(fd, &content)) { StatsdConfig config; if (config.ParseFromString(content)) { mConfigs[ConfigKey(uid, configName)] = config; ALOGD("map key uid=%d|name=%s", uid, name); } } close(fd); } } } void ConfigManager::update_saved_configs(const ConfigKey& key, const StatsdConfig& config) { mkdir(STATS_SERVICE_DIR, S_IRWXU); string file_name = StringPrintf("%s/%d-%s-%ld", STATS_SERVICE_DIR, key.GetUid(), key.GetName().c_str(), time(nullptr)); int fd = open(file_name.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR); if (fd != -1) { const int numBytes = config.ByteSize(); vector<uint8_t> buffer(numBytes); config.SerializeToArray(&buffer[0], numBytes); int result = write(fd, &buffer[0], numBytes); close(fd); bool wroteKey = (result == numBytes); ALOGD("wrote to file %d", wroteKey); } } static StatsdConfig build_fake_config() { Loading
cmds/statsd/src/config/ConfigManager.h +12 −4 Original line number Diff line number Diff line Loading @@ -46,9 +46,7 @@ public: virtual ~ConfigManager(); /** * Call to load the saved configs from disk. * * TODO: Implement me * Initialize ConfigListener by reading from disk and get updates. */ void Startup(); Loading Loading @@ -95,7 +93,12 @@ private: /** * Save the configs to disk. */ void update_saved_configs(); void update_saved_configs(const ConfigKey& key, const StatsdConfig& config); /** * Remove saved configs from disk. */ void remove_saved_configs(const ConfigKey& key); /** * The Configs that have been set. Each config should Loading @@ -112,6 +115,11 @@ private: * The ConfigListeners that will be told about changes. */ vector<sp<ConfigListener>> mListeners; /** * Call to load the saved configs from disk. */ void readConfigFromDisk(); }; } // namespace statsd Loading