Clean up how we handle configurations, and other assorted cleanup

- Add a ConfigManager class that tracks the configurations
  that have been passed to us.  Configurations are now
  tracked by tuples of (uid,tag), where the tag is an
  app-defined string, in case a single uid has multiple
  configurations.
- Move all of the initialization into StatsService.
- Get rid of the ability to have multiple LogListeners. Raw
  events are now pushed directly into StatsService, which
  can distribute them to the interested parties (and will
  eventually be able to do the proper locking).
- Add Log.h, which sets our LOG_TAG correctly.
- Move some of the related files that I expect will grow some
  into their own subdirectories.

Test: statsd_test
Test: adb shell cmd stats config ...
Test: adb shell dumpsys stats
Change-Id: I79487603003d8a842d5bd319741f1ecbf72063d1
diff --git a/cmds/statsd/src/config/ConfigKey.cpp b/cmds/statsd/src/config/ConfigKey.cpp
new file mode 100644
index 0000000..a365dc0
--- /dev/null
+++ b/cmds/statsd/src/config/ConfigKey.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config/ConfigKey.h"
+
+#include <sstream>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using std::ostringstream;
+
+ConfigKey::ConfigKey() {
+}
+
+ConfigKey::ConfigKey(const ConfigKey& that) : mName(that.mName), mUid(that.mUid) {
+}
+
+ConfigKey::ConfigKey(int uid, const string& name) : mName(name), mUid(uid) {
+}
+
+ConfigKey::~ConfigKey() {
+}
+
+string ConfigKey::ToString() const {
+    ostringstream out;
+    out << '(' << mUid << ',' << mName << ')';
+    return out.str();
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/config/ConfigKey.h b/cmds/statsd/src/config/ConfigKey.h
new file mode 100644
index 0000000..bbf20fd
--- /dev/null
+++ b/cmds/statsd/src/config/ConfigKey.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+
+#include <functional>
+#include <iostream>
+#include <string>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using std::hash;
+using std::ostream;
+using std::string;
+
+/**
+ * Uniquely identifies a configuration.
+ */
+class ConfigKey {
+public:
+    ConfigKey();
+    explicit ConfigKey(const ConfigKey& that);
+    ConfigKey(int uid, const string& name);
+    ~ConfigKey();
+
+    inline int GetUid() const {
+        return mUid;
+    }
+    inline const string& GetName() const {
+        return mName;
+    }
+
+    inline bool operator<(const ConfigKey& that) const {
+        if (mUid < that.mUid) {
+            return true;
+        }
+        if (mUid > that.mUid) {
+            return false;
+        }
+        return mName < that.mName;
+    };
+
+    inline bool operator==(const ConfigKey& that) const {
+        return mUid == that.mUid && mName == that.mName;
+    };
+
+    string ToString() const;
+
+private:
+    string mName;
+    int mUid;
+};
+
+inline ostream& operator<<(ostream& os, const ConfigKey& config) {
+    return os << config.ToString();
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
+
+/**
+ * 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!
+ */
+namespace std {
+
+using android::os::statsd::ConfigKey;
+
+template <>
+struct hash<ConfigKey> {
+    std::size_t operator()(const ConfigKey& key) const {
+        return (7 * key.GetUid()) ^ ((hash<string>()(key.GetName())));
+    }
+};
+
+}  // namespace std
diff --git a/cmds/statsd/src/config/ConfigListener.cpp b/cmds/statsd/src/config/ConfigListener.cpp
new file mode 100644
index 0000000..21a3f16
--- /dev/null
+++ b/cmds/statsd/src/config/ConfigListener.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config/ConfigListener.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+ConfigListener::ConfigListener() {
+}
+
+ConfigListener::~ConfigListener() {
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/config/ConfigListener.h b/cmds/statsd/src/config/ConfigListener.h
new file mode 100644
index 0000000..a58766d
--- /dev/null
+++ b/cmds/statsd/src/config/ConfigListener.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <frameworks/base/cmds/statsd/src/stats_log.pb.h>
+#include "config/ConfigKey.h"
+
+#include <utils/RefBase.h>
+#include <string>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using android::RefBase;
+using std::string;
+
+/**
+ * Callback for different subsystems inside statsd to implement to find out
+ * when a configuration has been added, updated or removed.
+ */
+class ConfigListener : public virtual RefBase {
+public:
+    ConfigListener();
+    virtual ~ConfigListener();
+
+    /**
+     * A configuration was added or updated.
+     */
+    virtual void OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config) = 0;
+
+    /**
+     * A configuration was removed.
+     */
+    virtual void OnConfigRemoved(const ConfigKey& key) = 0;
+};
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
new file mode 100644
index 0000000..2a4d6e2
--- /dev/null
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config/ConfigManager.h"
+
+#include "stats_util.h"
+
+#include <vector>
+
+#include <stdio.h>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+static StatsdConfig build_fake_config();
+
+ConfigManager::ConfigManager() {
+}
+
+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.
+
+    // this should be called from StatsService when it receives a statsd_config
+    UpdateConfig(ConfigKey(0, "fake"), build_fake_config());
+}
+
+void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
+    mListeners.push_back(listener);
+}
+
+void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& config) {
+    // Add to map
+    mConfigs[key] = config;
+    // Why doesn't this work? mConfigs.insert({key, config});
+
+    // Save to disk
+    update_saved_configs();
+
+    // Tell everyone
+    for (auto& listener : mListeners) {
+        listener->OnConfigUpdated(key, config);
+    }
+}
+
+void ConfigManager::RemoveConfig(const ConfigKey& key) {
+    unordered_map<ConfigKey, StatsdConfig>::iterator it = mConfigs.find(key);
+    if (it != mConfigs.end()) {
+        // Remove from map
+        mConfigs.erase(it);
+
+        // Save to disk
+        update_saved_configs();
+
+        // Tell everyone
+        for (auto& listener : mListeners) {
+            listener->OnConfigRemoved(key);
+        }
+    }
+    // If we didn't find it, just quietly ignore it.
+}
+
+void ConfigManager::RemoveConfigs(int uid) {
+    vector<ConfigKey> removed;
+
+    for (auto it = mConfigs.begin(); it != mConfigs.end();) {
+        // Remove from map
+        if (it->first.GetUid() == uid) {
+            removed.push_back(it->first);
+            it = mConfigs.erase(it);
+        } else {
+            it++;
+        }
+    }
+
+    // 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) {
+            listener->OnConfigRemoved(key);
+        }
+    }
+}
+
+void ConfigManager::Dump(FILE* out) {
+    fprintf(out, "CONFIGURATIONS (%d)\n", (int)mConfigs.size());
+    fprintf(out, "     uid name\n");
+    for (unordered_map<ConfigKey, StatsdConfig>::const_iterator it = mConfigs.begin();
+         it != mConfigs.end(); it++) {
+        fprintf(out, "  %6d %s\n", it->first.GetUid(), it->first.GetName().c_str());
+        // TODO: Print the contents of the config too.
+    }
+}
+
+void ConfigManager::update_saved_configs() {
+    // TODO: Implement me -- write to disk.
+}
+
+static StatsdConfig build_fake_config() {
+    // HACK: Hard code a test metric for counting screen on events...
+    StatsdConfig config;
+    config.set_config_id(12345L);
+
+    // One count metric to count screen on
+    CountMetric* metric = config.add_count_metric();
+    metric->set_metric_id(20150717L);
+    metric->set_what("SCREEN_IS_ON");
+    metric->mutable_bucket()->set_bucket_size_millis(30 * 1000L);
+
+    // One count metric to count PHOTO_CHANGE_OR_CHROME_CRASH
+    metric = config.add_count_metric();
+    metric->set_metric_id(20150718L);
+    metric->set_what("PHOTO_PROCESS_STATE_CHANGE");
+    metric->mutable_bucket()->set_bucket_size_millis(60 * 1000L);
+    metric->set_condition("SCREEN_IS_ON");
+
+    LogEntryMatcher* eventMatcher = config.add_log_entry_matcher();
+    eventMatcher->set_name("SCREEN_IS_ON");
+
+    SimpleLogEntryMatcher* simpleLogEntryMatcher = eventMatcher->mutable_simple_log_entry_matcher();
+    simpleLogEntryMatcher->add_tag(2 /*SCREEN_STATE_CHANGE*/);
+    simpleLogEntryMatcher->add_key_value_matcher()->mutable_key_matcher()->set_key(
+            1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+    simpleLogEntryMatcher->mutable_key_value_matcher(0)->set_eq_int(
+            2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+    eventMatcher = config.add_log_entry_matcher();
+    eventMatcher->set_name("SCREEN_IS_OFF");
+
+    simpleLogEntryMatcher = eventMatcher->mutable_simple_log_entry_matcher();
+    simpleLogEntryMatcher->add_tag(2 /*SCREEN_STATE_CHANGE*/);
+    simpleLogEntryMatcher->add_key_value_matcher()->mutable_key_matcher()->set_key(
+            1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+    simpleLogEntryMatcher->mutable_key_value_matcher(0)->set_eq_int(
+            1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
+
+    LogEntryMatcher* procEventMatcher = config.add_log_entry_matcher();
+    procEventMatcher->set_name("PHOTO_CRASH");
+
+    SimpleLogEntryMatcher* simpleLogMatcher2 = procEventMatcher->mutable_simple_log_entry_matcher();
+    simpleLogMatcher2->add_tag(1112 /*PROCESS_STATE_CHANGE*/);
+    KeyValueMatcher* keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
+    keyValueMatcher->mutable_key_matcher()->set_key(1002 /*pkg*/);
+    keyValueMatcher->set_eq_string(
+            "com.google.android.apps.photos" /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+    keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
+    keyValueMatcher->mutable_key_matcher()->set_key(1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+    keyValueMatcher->set_eq_int(2);
+
+    procEventMatcher = config.add_log_entry_matcher();
+    procEventMatcher->set_name("PHOTO_START");
+
+    simpleLogMatcher2 = procEventMatcher->mutable_simple_log_entry_matcher();
+    simpleLogMatcher2->add_tag(1112 /*PROCESS_STATE_CHANGE*/);
+    keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
+    keyValueMatcher->mutable_key_matcher()->set_key(1002 /*pkg*/);
+    keyValueMatcher->set_eq_string(
+            "com.google.android.apps.photos" /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+    keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
+    keyValueMatcher->mutable_key_matcher()->set_key(1 /*STATE*/);
+    keyValueMatcher->set_eq_int(1);
+
+    procEventMatcher = config.add_log_entry_matcher();
+    procEventMatcher->set_name("PHOTO_PROCESS_STATE_CHANGE");
+    LogEntryMatcher_Combination* combinationMatcher = procEventMatcher->mutable_combination();
+    combinationMatcher->set_operation(LogicalOperation::OR);
+    combinationMatcher->add_matcher("PHOTO_START");
+    combinationMatcher->add_matcher("PHOTO_CRASH");
+
+    procEventMatcher = config.add_log_entry_matcher();
+    procEventMatcher->set_name("CHROME_CRASH");
+
+    simpleLogMatcher2 = procEventMatcher->mutable_simple_log_entry_matcher();
+    simpleLogMatcher2->add_tag(1112 /*PROCESS_STATE_CHANGE*/);
+    keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
+    keyValueMatcher->mutable_key_matcher()->set_key(1002 /*pkg*/);
+    keyValueMatcher->set_eq_string(
+            "com.android.chrome" /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+    keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
+    keyValueMatcher->mutable_key_matcher()->set_key(1 /*STATE*/);
+    keyValueMatcher->set_eq_int(2);
+
+    procEventMatcher = config.add_log_entry_matcher();
+    procEventMatcher->set_name("PHOTO_CHANGE_OR_CHROME_CRASH");
+    combinationMatcher = procEventMatcher->mutable_combination();
+    combinationMatcher->set_operation(LogicalOperation::OR);
+    combinationMatcher->add_matcher("PHOTO_PROCESS_STATE_CHANGE");
+    combinationMatcher->add_matcher("CHROME_CRASH");
+
+    Condition* condition = config.add_condition();
+    condition->set_name("SCREEN_IS_ON");
+    SimpleCondition* simpleCondition = condition->mutable_simple_condition();
+    simpleCondition->set_start("SCREEN_IS_ON");
+    simpleCondition->set_stop("SCREEN_IS_OFF");
+
+    condition = config.add_condition();
+    condition->set_name("PHOTO_STARTED");
+
+    simpleCondition = condition->mutable_simple_condition();
+    simpleCondition->set_start("PHOTO_START");
+    simpleCondition->set_stop("PHOTO_CRASH");
+
+    condition = config.add_condition();
+    condition->set_name("SCREEN_IS_OFF");
+
+    simpleCondition = condition->mutable_simple_condition();
+    simpleCondition->set_start("SCREEN_IS_OFF");
+    simpleCondition->set_stop("SCREEN_IS_ON");
+
+    condition = config.add_condition();
+    condition->set_name("SCREEN_IS_EITHER_ON_OFF");
+
+    Condition_Combination* combination = condition->mutable_combination();
+    combination->set_operation(LogicalOperation::OR);
+    combination->add_condition("SCREEN_IS_ON");
+    combination->add_condition("SCREEN_IS_OFF");
+
+    condition = config.add_condition();
+    condition->set_name("SCREEN_IS_NEITHER_ON_OFF");
+
+    combination = condition->mutable_combination();
+    combination->set_operation(LogicalOperation::NOR);
+    combination->add_condition("SCREEN_IS_ON");
+    combination->add_condition("SCREEN_IS_OFF");
+
+    return config;
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h
new file mode 100644
index 0000000..5d73eaf
--- /dev/null
+++ b/cmds/statsd/src/config/ConfigManager.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "config/ConfigKey.h"
+#include "config/ConfigListener.h"
+
+#include <string>
+#include <unordered_map>
+
+#include <stdio.h>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using android::RefBase;
+using std::string;
+using std::unordered_map;
+using std::vector;
+
+/**
+ * Keeps track of which configurations have been set from various sources.
+ *
+ * TODO: Store the configs persistently too.
+ * TODO: Dump method for debugging.
+ */
+class ConfigManager : public virtual RefBase {
+public:
+    ConfigManager();
+    virtual ~ConfigManager();
+
+    /**
+     * Call to load the saved configs from disk.
+     *
+     * TODO: Implement me
+     */
+    void Startup();
+
+    /**
+     * Someone else wants to know about the configs.
+     */
+    void AddListener(const sp<ConfigListener>& listener);
+
+    /**
+     * A configuration was added or updated.
+     *
+     * Reports this to listeners.
+     */
+    void UpdateConfig(const ConfigKey& key, const StatsdConfig& data);
+
+    /**
+     * A configuration was removed.
+     *
+     * Reports this to listeners.
+     */
+    void RemoveConfig(const ConfigKey& key);
+
+    /**
+     * Remove all of the configs for the given uid.
+     */
+    void RemoveConfigs(int uid);
+
+    /**
+     * Text dump of our state for debugging.
+     */
+    void Dump(FILE* out);
+
+private:
+    /**
+     * Save the configs to disk.
+     */
+    void update_saved_configs();
+
+    /**
+     * The Configs that have been set
+     */
+    unordered_map<ConfigKey, StatsdConfig> mConfigs;
+
+    /**
+     * The ConfigListeners that will be told about changes.
+     */
+    vector<sp<ConfigListener>> mListeners;
+};
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android