Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04dacb54 authored by Howard Ro's avatar Howard Ro Committed by Android (Google) Code Review
Browse files

Merge "Write statsd configuration to disk and add cmd to clear it"

parents cd8d0c07 87d983cf
Loading
Loading
Loading
Loading
+33 −1
Original line number Diff line number Diff line
@@ -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"
@@ -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>
@@ -42,6 +43,7 @@ namespace os {
namespace statsd {

constexpr const char* kPermissionDump = "android.permission.DUMP";
#define STATS_SERVICE_DIR "/data/system/stats-service"

// ======================================================================
/**
@@ -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);
@@ -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");
@@ -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");
+5 −0
Original line number Diff line number Diff line
@@ -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.
     */
+1 −1
Original line number Diff line number Diff line
@@ -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 {

+91 −9
Original line number Diff line number Diff line
@@ -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 @@ 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());
@@ -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) {
@@ -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) {
@@ -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;

@@ -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() {
+12 −4
Original line number Diff line number Diff line
@@ -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();

@@ -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
@@ -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