Adding ability to add configs via adb command-line. The input
must be in serialized binary format. Also fixes small issue
in build rule related to proto lib.

Test: Manually tested that ADB command works without crashing.

Change-Id: Iba2e677561ff500adb601a598f73e8a7b32540e5
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index f49dfde..5f5e216 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -19,7 +19,7 @@
 #include <log/event_tag_map.h>
 #include <log/logprint.h>
 #include <utils/Errors.h>
-
+#include <cutils/log.h>
 #include <frameworks/base/cmds/statsd/src/stats_log.pb.h>
 
 using namespace android;
@@ -66,3 +66,9 @@
     }
 }
 
+void
+StatsLogProcessor::UpdateConfig(const int config_source, StatsdConfig config)
+{
+    m_configs[config_source] = config;
+    ALOGD("Updated configuration for source %i", config_source);
+}
\ No newline at end of file
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 23066ab9..d2daecd 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -19,8 +19,12 @@
 #include "LogReader.h"
 #include "DropboxWriter.h"
 
+#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
 #include <log/logprint.h>
 #include <stdio.h>
+#include <unordered_map>
+
+using android::os::statsd::StatsdConfig;
 
 class StatsLogProcessor : public LogListener
 {
@@ -30,6 +34,8 @@
 
     virtual void OnLogEvent(const log_msg& msg);
 
+    virtual void UpdateConfig(const int config_source, StatsdConfig config);
+
 private:
     /**
      * Numeric to string tag name mapping.
@@ -42,5 +48,11 @@
     AndroidLogFormat* m_format;
 
     DropboxWriter m_dropbox_writer;
+
+    /**
+     * Configs that have been specified, keyed by the source. This allows us to over-ride the config
+     * from a source later.
+     */
+    std::unordered_map<int, StatsdConfig> m_configs;
 };
 #endif //STATS_LOG_PROCESSOR_H
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 030c760..24413f6 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -19,9 +19,11 @@
 #include "StatsService.h"
 #include "DropboxReader.h"
 
+#include <android-base/file.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <cutils/log.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>
@@ -31,6 +33,7 @@
 #include <stdlib.h>
 
 using namespace android;
+using android::os::statsd::StatsdConfig;
 
 // ================================================================================
 StatsService::StatsService(const sp<Looper>& handlerLooper)
@@ -42,6 +45,13 @@
 {
 }
 
+status_t
+StatsService::setProcessor(const sp<StatsLogProcessor>& main_processor) {
+    m_processor = main_processor;
+    ALOGD("stats service set to processor %p", m_processor.get());
+    return NO_ERROR;
+}
+
 // Implement our own because the default binder implementation isn't
 // properly handling SHELL_COMMAND_TRANSACTION
 status_t
@@ -124,12 +134,33 @@
         if (!args[0].compare(String8("print-stats-log")) && args.size() > 1) {
             return doPrintStatsLog(out, args);
         }
+        if (!args[0].compare(String8("config"))) {
+            return doLoadConfig(in);
+        }
     }
 
     printCmdHelp(out);
     return NO_ERROR;
 }
 
+status_t
+StatsService::doLoadConfig(FILE* in)
+{
+    string content;
+    if (!android::base::ReadFdToString(fileno(in), &content)) {
+        return UNKNOWN_ERROR;
+    }
+    StatsdConfig config;
+    if (config.ParseFromString(content)) {
+        ALOGD("Config parsed from command line: %s", config.SerializeAsString().c_str());
+        m_processor->UpdateConfig(0, config);
+        return NO_ERROR;
+    } else {
+        ALOGD("Config failed to be parsed");
+        return UNKNOWN_ERROR;
+    }
+}
+
 Status
 StatsService::systemRunning()
 {
@@ -158,4 +189,5 @@
 StatsService::printCmdHelp(FILE* out) {
     fprintf(out, "Usage:\n");
     fprintf(out, "\t print-stats-log [tag_required] [timestamp_nsec_optional]\n");
+    fprintf(out, "\t config\t Loads a new config from command-line (must be proto in wire-encoded format).\n");
 }
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 556b07b..ef52b562 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -17,9 +17,12 @@
 #ifndef STATS_SERVICE_H
 #define STATS_SERVICE_H
 
+#include "StatsLogProcessor.h"
+
 #include <android/os/BnStatsManager.h>
 #include <binder/IResultReceiver.h>
 #include <binder/IShellCallback.h>
+#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
 #include <utils/Looper.h>
 
 #include <deque>
@@ -30,7 +33,7 @@
 using namespace android::binder;
 using namespace android::os;
 using namespace std;
-
+using android::os::statsd::StatsdConfig;
 
 // ================================================================================
 class StatsService : public BnStatsManager {
@@ -46,9 +49,13 @@
 
     virtual Status systemRunning();
 
+    virtual status_t setProcessor(const sp<StatsLogProcessor>& main_processor);
+
 private:
+    sp<StatsLogProcessor> m_processor; // Reference to the processor for updating configs.
     status_t doPrintStatsLog(FILE* out, const Vector<String8>& args);
     void printCmdHelp(FILE* out);
+    status_t doLoadConfig(FILE* in);
 };
 
 #endif // STATS_SERVICE_H
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index 2c721c7..f9265c6 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -57,7 +57,9 @@
 
     // Put the printer one first, so it will print before the real ones.
     reader->AddListener(new LogEntryPrinter(STDOUT_FILENO));
-    reader->AddListener(new StatsLogProcessor());
+    sp<StatsLogProcessor> main_processor = new StatsLogProcessor();
+    data->service->setProcessor(main_processor);
+    reader->AddListener(main_processor);
 
     // TODO: Construct and add real LogListners here.