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

Commit fdc123b6 authored by David Chen's avatar David Chen
Browse files

Adds locks to ConfigManager in statsd.

The ConfigManager can be triggered by Binder threads, so we should
lock any reads or writes to the config managers. We don't need to
lock within StatsService, so those methods simply call the methods
in ConfigManager.

Test: Test that statsd builds and unit tests pass.
Change-Id: I96904c4140a95dc60a419281c8c54f606a443fbc
parent 581576ef
Loading
Loading
Loading
Loading
+84 −34
Original line number Diff line number Diff line
@@ -59,47 +59,73 @@ void ConfigManager::StartupForTest() {
}

void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
    lock_guard<mutex> lock(mMutex);
    mListeners.push_back(listener);
}

void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& config) {
    vector<sp<ConfigListener>> broadcastList;
    {
        lock_guard <mutex> lock(mMutex);

        // Add to set
        mConfigs.insert(key);

        // Save to disk
    update_saved_configs(key, config);
        update_saved_configs_locked(key, config);

        for (sp<ConfigListener> listener : mListeners) {
            broadcastList.push_back(listener);
        }
    }

    // Tell everyone
    for (auto& listener : mListeners) {
    for (sp<ConfigListener> listener:broadcastList) {
        listener->OnConfigUpdated(key, config);
    }
}

void ConfigManager::SetConfigReceiver(const ConfigKey& key, const sp<IBinder>& intentSender) {
    lock_guard<mutex> lock(mMutex);
    mConfigReceivers[key] = intentSender;
}

void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
    lock_guard<mutex> lock(mMutex);
    mConfigReceivers.erase(key);
}

void ConfigManager::RemoveConfig(const ConfigKey& key) {
    vector<sp<ConfigListener>> broadcastList;
    {
        lock_guard <mutex> lock(mMutex);

        auto it = mConfigs.find(key);
        if (it != mConfigs.end()) {
            // Remove from map
            mConfigs.erase(it);

        // Tell everyone
        for (auto& listener : mListeners) {
            listener->OnConfigRemoved(key);
            for (sp<ConfigListener> listener : mListeners) {
                broadcastList.push_back(listener);
            }
        }

        auto itReceiver = mConfigReceivers.find(key);
        if (itReceiver != mConfigReceivers.end()) {
            // Remove from map
            mConfigReceivers.erase(itReceiver);
        }

        // Remove from disk. There can still be a lingering file on disk so we check
        // whether or not the config was on memory.
        remove_saved_configs(key);
    }

    for (sp<ConfigListener> listener:broadcastList) {
        listener->OnConfigRemoved(key);
    }
}

void ConfigManager::remove_saved_configs(const ConfigKey& key) {
    string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId());
    StorageManager::deleteSuffixedFiles(STATS_SERVICE_DIR, suffix.c_str());
@@ -107,6 +133,10 @@ void ConfigManager::remove_saved_configs(const ConfigKey& key) {

void ConfigManager::RemoveConfigs(int uid) {
    vector<ConfigKey> removed;
    vector<sp<ConfigListener>> broadcastList;
    {
        lock_guard <mutex> lock(mMutex);


        for (auto it = mConfigs.begin(); it != mConfigs.end();) {
            // Remove from map
@@ -120,10 +150,15 @@ void ConfigManager::RemoveConfigs(int uid) {
            }
        }

        for (sp<ConfigListener> listener : mListeners) {
            broadcastList.push_back(listener);
        }
    }

    // Remove separately so if they do anything in the callback they can't mess up our iteration.
    for (auto& key : removed) {
        // Tell everyone
        for (auto& listener : mListeners) {
        for (sp<ConfigListener> listener:broadcastList) {
            listener->OnConfigRemoved(key);
        }
    }
@@ -131,6 +166,10 @@ void ConfigManager::RemoveConfigs(int uid) {

void ConfigManager::RemoveAllConfigs() {
    vector<ConfigKey> removed;
    vector<sp<ConfigListener>> broadcastList;
    {
        lock_guard <mutex> lock(mMutex);


        for (auto it = mConfigs.begin(); it != mConfigs.end();) {
            // Remove from map
@@ -142,16 +181,23 @@ void ConfigManager::RemoveAllConfigs() {
            it = mConfigs.erase(it);
        }

        for (sp<ConfigListener> listener : mListeners) {
            broadcastList.push_back(listener);
        }
    }

    // Remove separately so if they do anything in the callback they can't mess up our iteration.
    for (auto& key : removed) {
        // Tell everyone
        for (auto& listener : mListeners) {
        for (sp<ConfigListener> listener:broadcastList) {
            listener->OnConfigRemoved(key);
        }
    }
}

vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
    lock_guard<mutex> lock(mMutex);

    vector<ConfigKey> ret;
    for (auto it = mConfigs.cbegin(); it != mConfigs.cend(); ++it) {
        ret.push_back(*it);
@@ -160,6 +206,8 @@ vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
}

const sp<android::IBinder> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
    lock_guard<mutex> lock(mMutex);

    auto it = mConfigReceivers.find(key);
    if (it == mConfigReceivers.end()) {
        return nullptr;
@@ -169,6 +217,8 @@ const sp<android::IBinder> ConfigManager::GetConfigReceiver(const ConfigKey& key
}

void ConfigManager::Dump(FILE* out) {
    lock_guard<mutex> lock(mMutex);

    fprintf(out, "CONFIGURATIONS (%d)\n", (int)mConfigs.size());
    fprintf(out, "     uid name\n");
    for (const auto& key : mConfigs) {
@@ -180,7 +230,7 @@ void ConfigManager::Dump(FILE* out) {
    }
}

void ConfigManager::update_saved_configs(const ConfigKey& key, const StatsdConfig& config) {
void ConfigManager::update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config) {
    // If there is a pre-existing config with same key we should first delete it.
    remove_saved_configs(key);

+4 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include "config/ConfigListener.h"

#include <map>
#include <mutex>
#include <set>
#include <string>

@@ -109,10 +110,12 @@ public:
    void Dump(FILE* out);

private:
    mutable std::mutex mMutex;

    /**
     * Save the configs to disk.
     */
    void update_saved_configs(const ConfigKey& key, const StatsdConfig& config);
    void update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config);

    /**
     * Remove saved configs from disk.