Statsd broadcast subscriber

Allows a uid that uploads a statsd config to additionally
register a BroadcastSubscriber with statsd. If statsd
detects an anomaly (according to the config's Alert),
statsd can inform a BroadcastSubscriber provided in the config.
The config uses a subscriberId (just an int) to identify the
BroadcastSubscriber. It then uses StatsManager.setBroadcastSubscriber
to associate that subscriberId with a given PendingIntent.
Then, when the anomaly is detected, statsd sends a broadcast
using that PendingIntent, alerting whoever was specified by
the config/setBroadcastSubscriber.

Bug: 70356901
Test: cts-tradefed run cts-dev -m CtsStatsdHostTestCases -t android.cts.statsd.alert.BroadcastSubscriberTests
Change-Id: I4d9ea9a6c8a85e61fadfd99c1513c55abbadd5e9
diff --git a/libs/services/Android.bp b/libs/services/Android.bp
index e5e865f..3d57fbd 100644
--- a/libs/services/Android.bp
+++ b/libs/services/Android.bp
@@ -19,6 +19,7 @@
     srcs: [
         ":IDropBoxManagerService.aidl",
         "src/os/DropBoxManager.cpp",
+        "src/os/StatsDimensionsValue.cpp",
         "src/os/StatsLogEventWrapper.cpp",
     ],
 
diff --git a/libs/services/include/android/os/StatsDimensionsValue.h b/libs/services/include/android/os/StatsDimensionsValue.h
new file mode 100644
index 0000000..cc0b056
--- /dev/null
+++ b/libs/services/include/android/os/StatsDimensionsValue.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+#ifndef STATS_DIMENSIONS_VALUE_H
+#define STATS_DIMENSIONS_VALUE_H
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <binder/Status.h>
+#include <utils/String16.h>
+#include <vector>
+
+namespace android {
+namespace os {
+
+// Represents a parcelable object. Used to send data from statsd to StatsCompanionService.java.
+class StatsDimensionsValue : public android::Parcelable {
+public:
+    StatsDimensionsValue();
+
+    StatsDimensionsValue(int32_t field, String16 value);
+    StatsDimensionsValue(int32_t field, int32_t value);
+    StatsDimensionsValue(int32_t field, int64_t value);
+    StatsDimensionsValue(int32_t field, bool value);
+    StatsDimensionsValue(int32_t field, float value);
+    StatsDimensionsValue(int32_t field, std::vector<StatsDimensionsValue> value);
+
+    virtual ~StatsDimensionsValue();
+
+    virtual android::status_t writeToParcel(android::Parcel* out) const override;
+    virtual android::status_t readFromParcel(const android::Parcel* in) override;
+
+private:
+    // Keep constants in sync with android/os/StatsDimensionsValue.java
+    // and stats_log.proto's DimensionValue.
+    static const int kStrValueType = 2;
+    static const int kIntValueType = 3;
+    static const int kLongValueType = 4;
+    static const int kBoolValueType = 5;
+    static const int kFloatValueType = 6;
+    static const int kTupleValueType = 7;
+
+    int32_t mField;
+    int32_t mValueType;
+
+    // This isn't very clever, but it isn't used for long-term storage, so it'll do.
+    String16 mStrValue;
+    int32_t mIntValue;
+    int64_t mLongValue;
+    bool mBoolValue;
+    float mFloatValue;
+    std::vector<StatsDimensionsValue> mTupleValue;
+};
+
+}  // namespace os
+}  // namespace android
+
+#endif // STATS_DIMENSIONS_VALUE_H
diff --git a/libs/services/src/os/StatsDimensionsValue.cpp b/libs/services/src/os/StatsDimensionsValue.cpp
new file mode 100644
index 0000000..0052e0b
--- /dev/null
+++ b/libs/services/src/os/StatsDimensionsValue.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#define LOG_TAG "StatsDimensionsValue"
+
+#include "android/os/StatsDimensionsValue.h"
+
+#include <cutils/log.h>
+
+using android::Parcel;
+using android::Parcelable;
+using android::status_t;
+using std::vector;
+
+namespace android {
+namespace os {
+
+StatsDimensionsValue::StatsDimensionsValue() {};
+
+StatsDimensionsValue::StatsDimensionsValue(int32_t field, String16 value) :
+    mField(field),
+    mValueType(kStrValueType),
+    mStrValue(value) {
+}
+StatsDimensionsValue::StatsDimensionsValue(int32_t field, int32_t value) :
+    mField(field),
+    mValueType(kIntValueType),
+    mIntValue(value) {
+}
+StatsDimensionsValue::StatsDimensionsValue(int32_t field, int64_t value) :
+    mField(field),
+    mValueType(kLongValueType),
+    mLongValue(value) {
+}
+StatsDimensionsValue::StatsDimensionsValue(int32_t field, bool value) :
+    mField(field),
+    mValueType(kBoolValueType),
+    mBoolValue(value) {
+}
+StatsDimensionsValue::StatsDimensionsValue(int32_t field, float value) :
+    mField(field),
+    mValueType(kFloatValueType),
+    mFloatValue(value) {
+}
+StatsDimensionsValue::StatsDimensionsValue(int32_t field, vector<StatsDimensionsValue> value) :
+    mField(field),
+    mValueType(kTupleValueType),
+    mTupleValue(value) {
+}
+
+StatsDimensionsValue::~StatsDimensionsValue() {}
+
+status_t
+StatsDimensionsValue::writeToParcel(Parcel* out) const {
+    status_t err ;
+
+    err = out->writeInt32(mField);
+    if (err != NO_ERROR) {
+        return err;
+    }
+    err = out->writeInt32(mValueType);
+    if (err != NO_ERROR) {
+        return err;
+    }
+    switch (mValueType) {
+        case kStrValueType:
+            err = out->writeString16(mStrValue);
+            break;
+        case kIntValueType:
+            err = out->writeInt32(mIntValue);
+            break;
+        case kLongValueType:
+            err = out->writeInt64(mLongValue);
+            break;
+        case kBoolValueType:
+            err = out->writeBool(mBoolValue);
+            break;
+        case kFloatValueType:
+            err = out->writeFloat(mFloatValue);
+            break;
+        case kTupleValueType:
+            {
+                int sz = mTupleValue.size();
+                err = out->writeInt32(sz);
+                if (err != NO_ERROR) {
+                    return err;
+                }
+                for (int i = 0; i < sz; ++i) {
+                    err = mTupleValue[i].writeToParcel(out);
+                    if (err != NO_ERROR) {
+                        return err;
+                    }
+                }
+            }
+            break;
+        default:
+            err = UNKNOWN_ERROR;
+            break;
+    }
+    return err;
+}
+
+status_t
+StatsDimensionsValue::readFromParcel(const Parcel* in)
+{
+    // Implement me if desired. We don't currently use this.
+    ALOGE("Cannot do c++ StatsDimensionsValue.readFromParcel(); it is not implemented.");
+    (void)in; // To prevent compile error of unused parameter 'in'
+    return UNKNOWN_ERROR;
+}
+
+}  // namespace os
+}  // namespace android