Write statsd configuration to disk and add cmd to clear it
Test: statsd, statsd_test
Change-Id: Iba37a7f295256d24969185bdde6cbf28f9b89a55
diff --git a/bin/src/config/ConfigManager.cpp b/bin/src/config/ConfigManager.cpp
index a9ce4a3..bc3a7b2 100644
--- a/bin/src/config/ConfigManager.cpp
+++ b/bin/src/config/ConfigManager.cpp
@@ -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() {
}
@@ -35,8 +42,7 @@
}
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());
@@ -52,7 +58,7 @@
// 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) {
@@ -74,8 +80,8 @@
// 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) {
@@ -85,6 +91,26 @@
// 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;
@@ -118,8 +144,64 @@
}
}
-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() {