Adds client API for interacting with statsd.

This API will primarily be used by GmsCore to send updated configs.
Also, sending a config will implicitly notify the StatsD that this
client wants to know when it should request data for this config.

We send a broadcast so that all interested subscribers can know if
data needs to be pulled.

Test: Manually tested that sending broadcast works via new adb
command added in StatsService.

Change-Id: I23cdd1df706036e14b32c3d01af30c3d4af819fa
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 11c5de1..07b1c5c 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -18,6 +18,8 @@
 #include "Log.h"
 
 #include "StatsService.h"
+#include "config/ConfigKey.h"
+#include "config/ConfigManager.h"
 #include "storage/DropboxReader.h"
 
 #include <android-base/file.h>
@@ -39,6 +41,8 @@
 namespace os {
 namespace statsd {
 
+constexpr const char* kPermissionDump = "android.permission.DUMP";
+
 // ======================================================================
 /**
  * Watches for the death of the stats companion (system process).
@@ -67,8 +71,8 @@
 {
     mUidMap = new UidMap();
     mConfigManager = new ConfigManager();
-    mProcessor = new StatsLogProcessor(mUidMap, [this](const vector<uint8_t>& log) {
-      pushLog(log);
+    mProcessor = new StatsLogProcessor(mUidMap, [](const vector<uint8_t>& log) {
+        // TODO: Update how we send data out of StatsD.
     });
 
     mConfigManager->AddListener(mProcessor);
@@ -198,6 +202,10 @@
         if (!args[0].compare(String8("pull-source")) && args.size() > 1) {
             return cmd_print_pulled_metrics(out, args);
         }
+
+        if (!args[0].compare(String8("send-broadcast"))) {
+            return cmd_trigger_broadcast(args);
+        }
     }
 
     print_cmd_help(out);
@@ -238,6 +246,19 @@
     fprintf(out, "                the UID parameter on eng builds. If UID is omitted the\n");
     fprintf(out, "                calling uid is used.\n");
     fprintf(out, "  NAME          The name of the configuration\n");
+    fprintf(out, "\n");
+    fprintf(out, "\n");
+    fprintf(out, "usage: adb shell cmd stats send-broadcast PACKAGE CLASS\n");
+    fprintf(out, "  Send a broadcast that triggers one subscriber to fetch metrics.\n");
+    fprintf(out, "  PACKAGE        The name of the package to receive the broadcast.\n");
+    fprintf(out, "  CLASS          The name of the class to receive the broadcast.\n");
+}
+
+status_t StatsService::cmd_trigger_broadcast(Vector<String8>& args) {
+    auto sc = getStatsCompanionService();
+    sc->sendBroadcast(String16(args[1]), String16(args[2]));
+    ALOGD("StatsService::trigger broadcast succeeded");
+    return NO_ERROR;
 }
 
 status_t StatsService::cmd_config(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
@@ -520,29 +541,51 @@
     mProcessor->OnLogEvent(event);
 }
 
-Status StatsService::requestPush() {
-    mProcessor->flush();
-    return Status::ok();
+Status StatsService::getData(const String16& key, vector<uint8_t>* output) {
+    IPCThreadState* ipc = IPCThreadState::self();
+    if (checkCallingPermission(String16(kPermissionDump),
+                               reinterpret_cast<int32_t*>(ipc->getCallingPid()),
+                               reinterpret_cast<int32_t*>(ipc->getCallingUid()))) {
+        // TODO: Implement this.
+        return Status::ok();
+    } else {
+        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
+    }
 }
 
-Status StatsService::pushLog(const vector<uint8_t>& log) {
-    std::lock_guard<std::mutex> lock(mLock);
-    for (size_t i = 0; i < mCallbacks.size(); i++) {
-        mCallbacks[i]->onReceiveLogs((vector<uint8_t>*)&log);
+Status StatsService::addConfiguration(const String16& key,
+                                      const vector <uint8_t>& config,
+                                      const String16& package, const String16& cls,
+                                      bool* success) {
+    IPCThreadState* ipc = IPCThreadState::self();
+    int32_t* uid = reinterpret_cast<int32_t*>(ipc->getCallingUid());
+    if (checkCallingPermission(String16(kPermissionDump),
+                               reinterpret_cast<int32_t*>(ipc->getCallingPid()), uid)) {
+        string keyString = string(String8(key).string());
+        ConfigKey configKey(*uid, keyString);
+        StatsdConfig cfg;
+        cfg.ParseFromArray(&config[0], config.size());
+        mConfigManager->UpdateConfig(configKey, cfg);
+        mConfigManager->SetConfigReceiver(configKey, string(String8(package).string()),
+                                          string(String8(cls).string()));
+        *success = true;
+        return Status::ok();
+    } else {
+        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
     }
-    return Status::ok();
 }
 
-Status StatsService::subscribeStatsLog(const sp<IStatsCallbacks>& callback) {
-    std::lock_guard<std::mutex> lock(mLock);
-    for (size_t i = 0; i < mCallbacks.size(); i++) {
-        if (mCallbacks[i] == callback) {
-           return Status::fromStatusT(-errno);
-        }
+Status StatsService::removeConfiguration(const String16& key, bool* success) {
+    IPCThreadState* ipc = IPCThreadState::self();
+    if (checkCallingPermission(String16(kPermissionDump),
+                               reinterpret_cast<int32_t*>(ipc->getCallingPid()),
+                               reinterpret_cast<int32_t*>(ipc->getCallingUid()))) {
+        // TODO: Implement this.
+        return Status::ok();
+    } else {
+        *success = false;
+        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
     }
-    mCallbacks.add(callback);
-    IInterface::asBinder(callback)->linkToDeath(this);
-    return Status::ok();
 }
 
 void StatsService::binderDied(const wp<IBinder>& who) {