Merge "Expose libstatspull as a stable C API"
diff --git a/libstats/pull/Android.bp b/libstats/pull/Android.bp
index 72eb0e9..2171aa4 100644
--- a/libstats/pull/Android.bp
+++ b/libstats/pull/Android.bp
@@ -32,7 +32,7 @@
],
export_include_dirs: ["include"],
shared_libs: [
- //TODO: use libbinder_ndk.
+ //TODO: use libbinder_ndk. Remove libservices.
"libbinder",
"libstatssocket",
"libservices",
@@ -40,5 +40,12 @@
static_libs: [
"liblog",
"libutils",
- ]
+ ],
+ // enumerate stable entry points for APEX use
+ stubs: {
+ symbol_file: "libstatspull.map.txt",
+ versions: [
+ "30",
+ ],
+ },
}
diff --git a/libstats/pull/include/stats_pull_atom_callback.h b/libstats/pull/include/stats_pull_atom_callback.h
index b779ac9..ad9b04e 100644
--- a/libstats/pull/include/stats_pull_atom_callback.h
+++ b/libstats/pull/include/stats_pull_atom_callback.h
@@ -15,41 +15,122 @@
*/
#pragma once
+#include <stats_event.h>
+
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
-/*
- * Metadata for registering a stats_pull_atom_callback.
+
+/**
+ * Opaque struct representing the metadata for registering an AStatsManager_PullAtomCallback.
*/
-typedef struct pull_atom_metadata {
- int64_t cool_down_ns;
- int64_t timeout_ns;
- int32_t* additive_fields;
- int32_t additive_fields_size;
-} pull_atom_metadata;
+struct AStatsManager_PullAtomMetadata;
+typedef struct AStatsManager_PullAtomMetadata AStatsManager_PullAtomMetadata;
-typedef struct pulled_stats_event_list pulled_stats_event_list;
+/**
+ * Allocate and initialize new PullAtomMetadata.
+ *
+ * Must call AStatsManager_PullAtomMetadata_release to free the memory.
+ */
+AStatsManager_PullAtomMetadata* AStatsManager_PullAtomMetadata_obtain();
-typedef int32_t status_pull_atom_return_t;
+/**
+ * Frees the memory held by this PullAtomMetadata
+ *
+ * After calling this, the PullAtomMetadata must not be used or modified in any way.
+ */
+void AStatsManager_PullAtomMetadata_release(AStatsManager_PullAtomMetadata* metadata);
+/**
+ * Set the cool down time of the pull in nanoseconds. If two successive pulls are issued
+ * within the cool down, a cached version of the first will be used for the second.
+ */
+void AStatsManager_PullAtomMetadata_setCoolDownNs(AStatsManager_PullAtomMetadata* metadata,
+ int64_t cool_down_ns);
+
+/**
+ * Set the maximum time the pull can take in nanoseconds.
+ */
+void AStatsManager_PullAtomMetadata_setTimeoutNs(AStatsManager_PullAtomMetadata* metadata,
+ int64_t timeout_ns);
+
+/**
+ * Set the additive fields of this pulled atom.
+ *
+ * This is only applicable for atoms which have a uid field. When tasks are run in
+ * isolated processes, the data will be attributed to the host uid. Additive fields
+ * will be combined when the non-additive fields are the same.
+ */
+void AStatsManager_PullAtomMetadata_setAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
+ int* additive_fields, int num_fields);
+
+/**
+ * Return codes for the result of a pull.
+ */
+typedef int32_t AStatsManager_PullAtomCallbackReturn;
enum {
- STATS_PULL_SUCCESS = 0,
- STATS_PULL_SKIP = 1,
+ // Value indicating that this pull was successful and that the result should be used.
+ AStatsManager_PULL_SUCCESS = 0,
+ // Value indicating that this pull was unsuccessful and that the result should not be used.
+ AStatsManager_PULL_SKIP = 1,
};
-typedef status_pull_atom_return_t (*stats_pull_atom_callback_t)(int32_t atom_tag,
- pulled_stats_event_list* data,
- void* cookie);
+/**
+ * Opaque struct representing a list of AStatsEvent objects.
+ */
+struct AStatsEventList;
+typedef struct AStatsEventList AStatsEventList;
-struct stats_event* add_stats_event_to_pull_data(pulled_stats_event_list* pull_data);
+/**
+ * Appends and returns an AStatsEvent to the end of the AStatsEventList.
+ *
+ * If an AStatsEvent is obtained in this manner, the memory is internally managed and
+ * AStatsEvent_release does not need to be called. The lifetime of the AStatsEvent is that of the
+ * AStatsEventList.
+ *
+ * The AStatsEvent does still need to be built by calling AStatsEvent_build.
+ */
+AStatsEvent* AStatsEventList_addStatsEvent(AStatsEventList* pull_data);
-void register_stats_pull_atom_callback(int32_t atom_tag, stats_pull_atom_callback_t callback,
- pull_atom_metadata* metadata, void* cookie);
+/**
+ * Callback interface for pulling atoms requested by the stats service.
+ *
+ * \param atom_tag the tag of the atom to pull.
+ * \param data an output parameter in which the caller should fill the results of the pull. This
+ * param cannot be NULL and it's lifetime is as long as the execution of the callback.
+ * It must not be accessed or modified after returning from the callback.
+ * \param cookie the opaque pointer passed in AStatsManager_registerPullAtomCallback.
+ * \return AStatsManager_PULL_SUCCESS if the pull was successful, or AStatsManager_PULL_SKIP if not.
+ */
+typedef AStatsManager_PullAtomCallbackReturn (*AStatsManager_PullAtomCallback)(
+ int32_t atom_tag, AStatsEventList* data, void* cookie);
+/**
+ * Registers a callback for an atom when that atom is to be pulled. The stats service will
+ * invoke the callback when the stats service determines that this atom needs to be
+ * pulled.
+ *
+ * \param atom_tag The tag of the atom for this pull atom callback.
+ * \param metadata Optional metadata specifying the timeout, cool down time, and
+ * additive fields for mapping isolated to host uids.
+ * This param is nullable, in which case defaults will be used.
+ * \param callback The callback to be invoked when the stats service pulls the atom.
+ * \param cookie A pointer that will be passed back to the callback.
+ * It has no meaning to statsd.
+ */
+void AStatsManager_registerPullAtomCallback(int32_t atom_tag,
+ AStatsManager_PullAtomCallback callback,
+ AStatsManager_PullAtomMetadata* metadata, void* cookie);
-void unregister_stats_pull_atom_callback(int32_t atom_tag);
+/**
+ * Unregisters a callback for an atom when that atom is to be pulled. Note that any ongoing
+ * pulls will still occur.
+ *
+ * \param atomTag The tag of the atom of which to unregister
+ */
+void AStatsManager_unregisterPullAtomCallback(int32_t atom_tag);
#ifdef __cplusplus
}
diff --git a/libstats/pull/libstatspull.map.txt b/libstats/pull/libstatspull.map.txt
new file mode 100644
index 0000000..dc3fd8b
--- /dev/null
+++ b/libstats/pull/libstatspull.map.txt
@@ -0,0 +1,13 @@
+LIBSTATSPULL {
+ global:
+ AStatsManager_PullAtomMetadata_obtain; # apex # introduced=30
+ AStatsManager_PullAtomMetadata_release; # apex # introduced=30
+ AStatsManager_PullAtomMetadata_setCoolDownNs; # apex # introduced=30
+ AStatsManager_PullAtomMetadata_setTimeoutNs; # apex # introduced=30
+ AStatsManager_PullAtomMetadata_setAdditiveFields; # apex # introduced=30
+ AStatsEventList_addStatsEvent; # apex # introduced=30
+ AStatsManager_registerPullAtomCallback; # apex # introduced=30
+ AStatsManager_unregisterPullAtomCallback; # apex # introduced=30
+ local:
+ *;
+};
diff --git a/libstats/pull/stats_pull_atom_callback.cpp b/libstats/pull/stats_pull_atom_callback.cpp
index e8fc2ea..9c497b8 100644
--- a/libstats/pull/stats_pull_atom_callback.cpp
+++ b/libstats/pull/stats_pull_atom_callback.cpp
@@ -28,12 +28,12 @@
#include <thread>
-struct pulled_stats_event_list {
- std::vector<stats_event*> data;
+struct AStatsEventList {
+ std::vector<AStatsEvent*> data;
};
-struct stats_event* add_stats_event_to_pull_data(pulled_stats_event_list* pull_data) {
- struct stats_event* event = stats_event_obtain();
+AStatsEvent* AStatsEventList_addStatsEvent(AStatsEventList* pull_data) {
+ AStatsEvent* event = AStatsEvent_obtain();
pull_data->data.push_back(event);
return event;
}
@@ -41,9 +41,42 @@
static const int64_t DEFAULT_COOL_DOWN_NS = 1000000000LL; // 1 second.
static const int64_t DEFAULT_TIMEOUT_NS = 10000000000LL; // 10 seconds.
+struct AStatsManager_PullAtomMetadata {
+ int64_t cool_down_ns;
+ int64_t timeout_ns;
+ std::vector<int32_t> additive_fields;
+};
+
+AStatsManager_PullAtomMetadata* AStatsManager_PullAtomMetadata_obtain() {
+ AStatsManager_PullAtomMetadata* metadata = new AStatsManager_PullAtomMetadata();
+ metadata->cool_down_ns = DEFAULT_COOL_DOWN_NS;
+ metadata->timeout_ns = DEFAULT_TIMEOUT_NS;
+ metadata->additive_fields = std::vector<int32_t>();
+ return metadata;
+}
+
+void AStatsManager_PullAtomMetadata_release(AStatsManager_PullAtomMetadata* metadata) {
+ delete metadata;
+}
+
+void AStatsManager_PullAtomMetadata_setCoolDownNs(AStatsManager_PullAtomMetadata* metadata,
+ int64_t cool_down_ns) {
+ metadata->cool_down_ns = cool_down_ns;
+}
+
+void AStatsManager_PullAtomMetadata_setTimeoutNs(AStatsManager_PullAtomMetadata* metadata,
+ int64_t timeout_ns) {
+ metadata->timeout_ns = timeout_ns;
+}
+
+void AStatsManager_PullAtomMetadata_setAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
+ int* additive_fields, int num_fields) {
+ metadata->additive_fields.assign(additive_fields, additive_fields + num_fields);
+}
+
class StatsPullAtomCallbackInternal : public android::os::BnPullAtomCallback {
public:
- StatsPullAtomCallbackInternal(const stats_pull_atom_callback_t callback, void* cookie,
+ StatsPullAtomCallbackInternal(const AStatsManager_PullAtomCallback callback, void* cookie,
const int64_t coolDownNs, const int64_t timeoutNs,
const std::vector<int32_t> additiveFields)
: mCallback(callback),
@@ -55,15 +88,16 @@
::android::binder::Status onPullAtom(
int32_t atomTag,
const ::android::sp<::android::os::IPullAtomResultReceiver>& resultReceiver) override {
- pulled_stats_event_list statsEventList;
+ AStatsEventList statsEventList;
+ statsEventList.data.clear();
int successInt = mCallback(atomTag, &statsEventList, mCookie);
- bool success = successInt == STATS_PULL_SUCCESS;
+ bool success = successInt == AStatsManager_PULL_SUCCESS;
// Convert stats_events into StatsEventParcels.
std::vector<android::util::StatsEventParcel> parcels;
for (int i = 0; i < statsEventList.data.size(); i++) {
size_t size;
- uint8_t* buffer = stats_event_get_buffer(statsEventList.data[i], &size);
+ uint8_t* buffer = AStatsEvent_getBuffer(statsEventList.data[i], &size);
android::util::StatsEventParcel p;
// vector.assign() creates a copy, but this is inevitable unless
@@ -74,7 +108,7 @@
resultReceiver->pullFinished(atomTag, success, parcels);
for (int i = 0; i < statsEventList.data.size(); i++) {
- stats_event_release(statsEventList.data[i]);
+ AStatsEvent_release(statsEventList.data[i]);
}
return android::binder::Status::ok();
}
@@ -84,7 +118,7 @@
const std::vector<int32_t>& getAdditiveFields() const { return mAdditiveFields; }
private:
- const stats_pull_atom_callback_t mCallback;
+ const AStatsManager_PullAtomCallback mCallback;
void* mCookie;
const int64_t mCoolDownNs;
const int64_t mTimeoutNs;
@@ -165,15 +199,16 @@
statsService->unregisterNativePullAtomCallback(atomTag);
}
-void register_stats_pull_atom_callback(int32_t atom_tag, stats_pull_atom_callback_t callback,
- pull_atom_metadata* metadata, void* cookie) {
+void AStatsManager_registerPullAtomCallback(int32_t atom_tag,
+ AStatsManager_PullAtomCallback callback,
+ AStatsManager_PullAtomMetadata* metadata,
+ void* cookie) {
int64_t coolDownNs = metadata == nullptr ? DEFAULT_COOL_DOWN_NS : metadata->cool_down_ns;
int64_t timeoutNs = metadata == nullptr ? DEFAULT_TIMEOUT_NS : metadata->timeout_ns;
std::vector<int32_t> additiveFields;
- if (metadata != nullptr && metadata->additive_fields != nullptr) {
- additiveFields.assign(metadata->additive_fields,
- metadata->additive_fields + metadata->additive_fields_size);
+ if (metadata != nullptr) {
+ additiveFields = metadata->additive_fields;
}
android::sp<StatsPullAtomCallbackInternal> callbackBinder = new StatsPullAtomCallbackInternal(
@@ -189,7 +224,7 @@
registerThread.detach();
}
-void unregister_stats_pull_atom_callback(int32_t atom_tag) {
+void AStatsManager_unregisterPullAtomCallback(int32_t atom_tag) {
{
std::lock_guard<std::mutex> lg(pullAtomMutex);
// Always remove the puller from our map.
diff --git a/libstats/push_compat/StatsEventCompat.cpp b/libstats/push_compat/StatsEventCompat.cpp
index edfa070..de458b3 100644
--- a/libstats/push_compat/StatsEventCompat.cpp
+++ b/libstats/push_compat/StatsEventCompat.cpp
@@ -38,7 +38,7 @@
// definitions of static class variables
bool StatsEventCompat::mAttemptedLoad = false;
-struct stats_event_api_table* StatsEventCompat::mStatsEventApi = nullptr;
+void* StatsEventCompat::mStatsEventApi = nullptr;
std::mutex StatsEventCompat::mLoadLock;
StatsEventCompat::StatsEventCompat() : mEventQ(kStatsEventTag) {
@@ -49,7 +49,8 @@
if (!mAttemptedLoad) {
void* handle = dlopen("libstatssocket.so", RTLD_NOW);
if (handle) {
- mStatsEventApi = (struct stats_event_api_table*)dlsym(handle, "table");
+ // mStatsEventApi = (struct AStatsEvent_apiTable*)dlsym(handle,
+ // "table");
} else {
ALOGE("dlopen failed: %s\n", dlerror());
}
@@ -58,19 +59,19 @@
}
if (mStatsEventApi) {
- mEventR = mStatsEventApi->obtain();
+ // mEventR = mStatsEventApi->obtain();
} else if (!mPlatformAtLeastR) {
mEventQ << android::elapsedRealtimeNano();
}
}
StatsEventCompat::~StatsEventCompat() {
- if (mStatsEventApi) mStatsEventApi->release(mEventR);
+ // if (mStatsEventApi) mStatsEventApi->release(mEventR);
}
void StatsEventCompat::setAtomId(int32_t atomId) {
if (mStatsEventApi) {
- mStatsEventApi->set_atom_id(mEventR, (uint32_t)atomId);
+ // mStatsEventApi->setAtomId(mEventR, (uint32_t)atomId);
} else if (!mPlatformAtLeastR) {
mEventQ << atomId;
}
@@ -78,7 +79,7 @@
void StatsEventCompat::writeInt32(int32_t value) {
if (mStatsEventApi) {
- mStatsEventApi->write_int32(mEventR, value);
+ // mStatsEventApi->writeInt32(mEventR, value);
} else if (!mPlatformAtLeastR) {
mEventQ << value;
}
@@ -86,7 +87,7 @@
void StatsEventCompat::writeInt64(int64_t value) {
if (mStatsEventApi) {
- mStatsEventApi->write_int64(mEventR, value);
+ // mStatsEventApi->writeInt64(mEventR, value);
} else if (!mPlatformAtLeastR) {
mEventQ << value;
}
@@ -94,7 +95,7 @@
void StatsEventCompat::writeFloat(float value) {
if (mStatsEventApi) {
- mStatsEventApi->write_float(mEventR, value);
+ // mStatsEventApi->writeFloat(mEventR, value);
} else if (!mPlatformAtLeastR) {
mEventQ << value;
}
@@ -102,7 +103,7 @@
void StatsEventCompat::writeBool(bool value) {
if (mStatsEventApi) {
- mStatsEventApi->write_bool(mEventR, value);
+ // mStatsEventApi->writeBool(mEventR, value);
} else if (!mPlatformAtLeastR) {
mEventQ << value;
}
@@ -110,7 +111,7 @@
void StatsEventCompat::writeByteArray(const char* buffer, size_t length) {
if (mStatsEventApi) {
- mStatsEventApi->write_byte_array(mEventR, (const uint8_t*)buffer, length);
+ // mStatsEventApi->writeByteArray(mEventR, (const uint8_t*)buffer, length);
} else if (!mPlatformAtLeastR) {
mEventQ.AppendCharArray(buffer, length);
}
@@ -120,7 +121,7 @@
if (value == nullptr) value = "";
if (mStatsEventApi) {
- mStatsEventApi->write_string8(mEventR, value);
+ // mStatsEventApi->writeString(mEventR, value);
} else if (!mPlatformAtLeastR) {
mEventQ << value;
}
@@ -129,8 +130,8 @@
void StatsEventCompat::writeAttributionChain(const int32_t* uids, size_t numUids,
const vector<const char*>& tags) {
if (mStatsEventApi) {
- mStatsEventApi->write_attribution_chain(mEventR, (const uint32_t*)uids, tags.data(),
- (uint8_t)numUids);
+ // mStatsEventApi->writeAttributionChain(mEventR, (const uint32_t*)uids, tags.data(),
+ // (uint8_t)numUids);
} else if (!mPlatformAtLeastR) {
mEventQ.begin();
for (size_t i = 0; i < numUids; i++) {
@@ -148,26 +149,8 @@
const map<int, int64_t>& int64Map,
const map<int, const char*>& stringMap,
const map<int, float>& floatMap) {
- if (mStatsEventApi) {
- vector<struct key_value_pair> pairs;
-
- for (const auto& it : int32Map) {
- pairs.push_back({.key = it.first, .valueType = INT32_TYPE, .int32Value = it.second});
- }
- for (const auto& it : int64Map) {
- pairs.push_back({.key = it.first, .valueType = INT64_TYPE, .int64Value = it.second});
- }
- for (const auto& it : stringMap) {
- pairs.push_back({.key = it.first, .valueType = STRING_TYPE, .stringValue = it.second});
- }
- for (const auto& it : floatMap) {
- pairs.push_back({.key = it.first, .valueType = FLOAT_TYPE, .floatValue = it.second});
- }
-
- mStatsEventApi->write_key_value_pairs(mEventR, pairs.data(), (uint8_t)pairs.size());
- }
-
- else if (!mPlatformAtLeastR) {
+ // Key value pairs are not supported with AStatsEvent.
+ if (!mPlatformAtLeastR) {
mEventQ.begin();
writeKeyValuePairMap(int32Map);
writeKeyValuePairMap(int64Map);
@@ -194,19 +177,25 @@
template void StatsEventCompat::writeKeyValuePairMap<const char*>(const map<int, const char*>&);
void StatsEventCompat::addBoolAnnotation(uint8_t annotationId, bool value) {
- if (mStatsEventApi) mStatsEventApi->add_bool_annotation(mEventR, annotationId, value);
+ // Workaround for unused params.
+ (void)annotationId;
+ (void)value;
+ // if (mStatsEventApi) mStatsEventApi->addBoolAnnotation(mEventR, annotationId, value);
// Don't do anything if on Q.
}
void StatsEventCompat::addInt32Annotation(uint8_t annotationId, int32_t value) {
- if (mStatsEventApi) mStatsEventApi->add_int32_annotation(mEventR, annotationId, value);
+ // Workaround for unused params.
+ (void)annotationId;
+ (void)value;
+ // if (mStatsEventApi) mStatsEventApi->addInt32Annotation(mEventR, annotationId, value);
// Don't do anything if on Q.
}
int StatsEventCompat::writeToSocket() {
if (mStatsEventApi) {
- mStatsEventApi->build(mEventR);
- return mStatsEventApi->write(mEventR);
+ // mStatsEventApi->build(mEventR);
+ // return mStatsEventApi->write(mEventR);
}
if (!mPlatformAtLeastR) return mEventQ.write(LOG_ID_STATS);
diff --git a/libstats/push_compat/include/StatsEventCompat.h b/libstats/push_compat/include/StatsEventCompat.h
index a8cde68..ad423a1 100644
--- a/libstats/push_compat/include/StatsEventCompat.h
+++ b/libstats/push_compat/include/StatsEventCompat.h
@@ -57,10 +57,11 @@
const static bool mPlatformAtLeastR;
static bool mAttemptedLoad;
static std::mutex mLoadLock;
- static struct stats_event_api_table* mStatsEventApi;
+ // static struct AStatsEvent_apiTable* mStatsEventApi;
+ static void* mStatsEventApi;
// non-static member variables
- struct stats_event* mEventR = nullptr;
+ AStatsEvent* mEventR = nullptr;
stats_event_list mEventQ;
template <class T>
diff --git a/libstats/socket/Android.bp b/libstats/socket/Android.bp
index 8a43d85..f36b214 100644
--- a/libstats/socket/Android.bp
+++ b/libstats/socket/Android.bp
@@ -45,7 +45,7 @@
stubs: {
symbol_file: "libstatssocket.map.txt",
versions: [
- "1",
+ "30",
],
}
}
diff --git a/libstats/socket/benchmark/stats_event_benchmark.cpp b/libstats/socket/benchmark/stats_event_benchmark.cpp
index 9488168..3fc6e55 100644
--- a/libstats/socket/benchmark/stats_event_benchmark.cpp
+++ b/libstats/socket/benchmark/stats_event_benchmark.cpp
@@ -17,14 +17,14 @@
#include "benchmark/benchmark.h"
#include "stats_event.h"
-static struct stats_event* constructStatsEvent() {
- struct stats_event* event = stats_event_obtain();
- stats_event_set_atom_id(event, 100);
+static AStatsEvent* constructStatsEvent() {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
// randomly sample atom size
int numElements = rand() % 800;
for (int i = 0; i < numElements; i++) {
- stats_event_write_int32(event, i);
+ AStatsEvent_writeInt32(event, i);
}
return event;
@@ -32,10 +32,10 @@
static void BM_stats_event_truncate_buffer(benchmark::State& state) {
while (state.KeepRunning()) {
- struct stats_event* event = constructStatsEvent();
- stats_event_build(event);
- stats_event_write(event);
- stats_event_release(event);
+ AStatsEvent* event = constructStatsEvent();
+ AStatsEvent_build(event);
+ AStatsEvent_write(event);
+ AStatsEvent_release(event);
}
}
@@ -43,11 +43,11 @@
static void BM_stats_event_full_buffer(benchmark::State& state) {
while (state.KeepRunning()) {
- struct stats_event* event = constructStatsEvent();
- stats_event_truncate_buffer(event, false);
- stats_event_build(event);
- stats_event_write(event);
- stats_event_release(event);
+ AStatsEvent* event = constructStatsEvent();
+ AStatsEvent_truncateBuffer(event, false);
+ AStatsEvent_build(event);
+ AStatsEvent_write(event);
+ AStatsEvent_release(event);
}
}
diff --git a/libstats/socket/include/stats_event.h b/libstats/socket/include/stats_event.h
index 080e957..6a2d9cd 100644
--- a/libstats/socket/include/stats_event.h
+++ b/libstats/socket/include/stats_event.h
@@ -26,17 +26,17 @@
* This code defines and encapsulates the socket protocol.
*
* Usage:
- * struct stats_event* event = stats_event_obtain();
+ * AStatsEvent* event = AStatsEvent_obtain();
*
- * stats_event_set_atom_id(event, atomId);
- * stats_event_write_int32(event, 24);
- * stats_event_add_bool_annotation(event, 1, true); // annotations apply to the previous field
- * stats_event_add_int32_annotation(event, 2, 128);
- * stats_event_write_float(event, 2.0);
+ * AStatsEvent_setAtomId(event, atomId);
+ * AStatsEvent_writeInt32(event, 24);
+ * AStatsEvent_addBoolAnnotation(event, 1, true); // annotations apply to the previous field
+ * AStatsEvent_addInt32Annotation(event, 2, 128);
+ * AStatsEvent_writeFloat(event, 2.0);
*
- * stats_event_build(event);
- * stats_event_write(event);
- * stats_event_release(event);
+ * AStatsEvent_build(event);
+ * AStatsEvent_write(event);
+ * AStatsEvent_release(event);
*
* Notes:
* (a) write_<type>() and add_<type>_annotation() should be called in the order that fields
@@ -47,115 +47,118 @@
* (e) All strings should be encoded using UTF8.
*/
-/* ERRORS */
-#define ERROR_NO_TIMESTAMP 0x1
-#define ERROR_NO_ATOM_ID 0x2
-#define ERROR_OVERFLOW 0x4
-#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
-#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
-#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
-#define ERROR_INVALID_ANNOTATION_ID 0x40
-#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
-#define ERROR_TOO_MANY_ANNOTATIONS 0x100
-#define ERROR_TOO_MANY_FIELDS 0x200
-#define ERROR_INVALID_VALUE_TYPE 0x400
-#define ERROR_STRING_NOT_NULL_TERMINATED 0x800
-
-/* TYPE IDS */
-#define INT32_TYPE 0x00
-#define INT64_TYPE 0x01
-#define STRING_TYPE 0x02
-#define LIST_TYPE 0x03
-#define FLOAT_TYPE 0x04
-#define BOOL_TYPE 0x05
-#define BYTE_ARRAY_TYPE 0x06
-#define OBJECT_TYPE 0x07
-#define KEY_VALUE_PAIRS_TYPE 0x08
-#define ATTRIBUTION_CHAIN_TYPE 0x09
-#define ERROR_TYPE 0x0F
-
#ifdef __cplusplus
extern "C" {
#endif // __CPLUSPLUS
-struct stats_event;
-
-/* SYSTEM API */
-struct stats_event* stats_event_obtain();
-// The build function can be called multiple times without error. If the event
-// has been built before, this function is a no-op.
-void stats_event_build(struct stats_event* event);
-int stats_event_write(struct stats_event* event);
-void stats_event_release(struct stats_event* event);
-
-void stats_event_set_atom_id(struct stats_event* event, uint32_t atomId);
-
-void stats_event_write_int32(struct stats_event* event, int32_t value);
-void stats_event_write_int64(struct stats_event* event, int64_t value);
-void stats_event_write_float(struct stats_event* event, float value);
-void stats_event_write_bool(struct stats_event* event, bool value);
-
-void stats_event_write_byte_array(struct stats_event* event, const uint8_t* buf, size_t numBytes);
-
-// Buf must be null-terminated.
-void stats_event_write_string8(struct stats_event* event, const char* value);
-
-// Tags must be null-terminated.
-void stats_event_write_attribution_chain(struct stats_event* event, const uint32_t* uids,
- const char* const* tags, uint8_t numNodes);
-
-/* key_value_pair struct can be constructed as follows:
- * struct key_value_pair pair = {.key = key, .valueType = STRING_TYPE,
- * .stringValue = buf};
+/**
+ * Opaque struct use to represent a StatsEvent. It builds and stores the data that is sent to
+ * statsd.
*/
-struct key_value_pair {
- int32_t key;
- uint8_t valueType; // expected to be INT32_TYPE, INT64_TYPE, FLOAT_TYPE, or STRING_TYPE
- union {
- int32_t int32Value;
- int64_t int64Value;
- float floatValue;
- const char* stringValue; // must be null terminated
- };
-};
+struct AStatsEvent;
+typedef struct AStatsEvent AStatsEvent;
-void stats_event_write_key_value_pairs(struct stats_event* event, struct key_value_pair* pairs,
- uint8_t numPairs);
+/**
+ * Returns a new AStatsEvent. If you call this function, you must call AStatsEvent_release to free
+ * the allocated memory.
+ */
+AStatsEvent* AStatsEvent_obtain();
-void stats_event_add_bool_annotation(struct stats_event* event, uint8_t annotationId, bool value);
-void stats_event_add_int32_annotation(struct stats_event* event, uint8_t annotationId,
- int32_t value);
+/**
+ * Builds and finalizes the StatsEvent.
+ *
+ * After this function, the StatsEvent must not be modified in any way other than calling release or
+ * write. Build must be always be called before AStatsEvent_write.
+ *
+ * Build can be called multiple times without error.
+ * If the event has been built before, this function is a no-op.
+ */
+void AStatsEvent_build(AStatsEvent* event);
-uint32_t stats_event_get_atom_id(struct stats_event* event);
+/**
+ * Writes the StatsEvent to the stats log.
+ *
+ * After calling this, AStatsEvent_release must be called,
+ * and is the only function that can be safely called.
+ */
+int AStatsEvent_write(AStatsEvent* event);
+
+/**
+ * Frees the memory held by this StatsEvent
+ *
+ * After calling this, the StatsEvent must not be used or modified in any way.
+ */
+void AStatsEvent_release(AStatsEvent* event);
+
+/**
+ * Sets the atom id for this StatsEvent.
+ **/
+void AStatsEvent_setAtomId(AStatsEvent* event, uint32_t atomId);
+
+/**
+ * Writes an int32_t field to this StatsEvent.
+ **/
+void AStatsEvent_writeInt32(AStatsEvent* event, int32_t value);
+
+/**
+ * Writes an int64_t field to this StatsEvent.
+ **/
+void AStatsEvent_writeInt64(AStatsEvent* event, int64_t value);
+
+/**
+ * Writes a float field to this StatsEvent.
+ **/
+void AStatsEvent_writeFloat(AStatsEvent* event, float value);
+
+/**
+ * Write a bool field to this StatsEvent.
+ **/
+void AStatsEvent_writeBool(AStatsEvent* event, bool value);
+
+/**
+ * Write a byte array field to this StatsEvent.
+ **/
+void AStatsEvent_writeByteArray(AStatsEvent* event, const uint8_t* buf, size_t numBytes);
+
+/**
+ * Write a string field to this StatsEvent.
+ *
+ * The string must be null-terminated.
+ **/
+void AStatsEvent_writeString(AStatsEvent* event, const char* value);
+
+/**
+ * Write an attribution chain field to this StatsEvent.
+ *
+ * The sizes of uids and tags must be equal. The AttributionNode at position i is
+ * made up of uids[i] and tags[i].
+ *
+ * \param uids array of uids in the attribution chain.
+ * \param tags array of tags in the attribution chain. Each tag must be null-terminated.
+ * \param numNodes the number of AttributionNodes in the attribution chain. This is the length of
+ * the uids and the tags.
+ **/
+void AStatsEvent_writeAttributionChain(AStatsEvent* event, const uint32_t* uids,
+ const char* const* tags, uint8_t numNodes);
+
+/**
+ * Write a bool annotation for the previous field written.
+ **/
+void AStatsEvent_addBoolAnnotation(AStatsEvent* event, uint8_t annotationId, bool value);
+
+/**
+ * Write an integer annotation for the previous field written.
+ **/
+void AStatsEvent_addInt32Annotation(AStatsEvent* event, uint8_t annotationId, int32_t value);
+
+// Internal/test APIs. Should not be exposed outside of the APEX.
+uint32_t AStatsEvent_getAtomId(AStatsEvent* event);
// Size is an output parameter.
-uint8_t* stats_event_get_buffer(struct stats_event* event, size_t* size);
-uint32_t stats_event_get_errors(struct stats_event* event);
-
-// This table is used by StatsEventCompat to access the stats_event API.
-struct stats_event_api_table {
- struct stats_event* (*obtain)(void);
- void (*build)(struct stats_event*);
- int (*write)(struct stats_event*);
- void (*release)(struct stats_event*);
- void (*set_atom_id)(struct stats_event*, uint32_t);
- void (*write_int32)(struct stats_event*, int32_t);
- void (*write_int64)(struct stats_event*, int64_t);
- void (*write_float)(struct stats_event*, float);
- void (*write_bool)(struct stats_event*, bool);
- void (*write_byte_array)(struct stats_event*, const uint8_t*, size_t);
- void (*write_string8)(struct stats_event*, const char*);
- void (*write_attribution_chain)(struct stats_event*, const uint32_t*, const char* const*,
- uint8_t);
- void (*write_key_value_pairs)(struct stats_event*, struct key_value_pair*, uint8_t);
- void (*add_bool_annotation)(struct stats_event*, uint8_t, bool);
- void (*add_int32_annotation)(struct stats_event*, uint8_t, int32_t);
- uint32_t (*get_atom_id)(struct stats_event*);
- uint8_t* (*get_buffer)(struct stats_event*, size_t*);
- uint32_t (*get_errors)(struct stats_event*);
-};
+uint8_t* AStatsEvent_getBuffer(AStatsEvent* event, size_t* size);
+uint32_t AStatsEvent_getErrors(AStatsEvent* event);
// exposed for benchmarking only
-void stats_event_truncate_buffer(struct stats_event* event, bool truncate);
+void AStatsEvent_truncateBuffer(struct AStatsEvent* event, bool truncate);
#ifdef __cplusplus
}
diff --git a/libstats/socket/libstatssocket.map.txt b/libstats/socket/libstatssocket.map.txt
index 55bfbda..e2e7ae3 100644
--- a/libstats/socket/libstatssocket.map.txt
+++ b/libstats/socket/libstatssocket.map.txt
@@ -1,23 +1,19 @@
LIBSTATSSOCKET {
global:
- stats_event_obtain; # apex # introduced=1
- stats_event_build; # apex # introduced=1
- stats_event_write; # apex # introduced=1
- stats_event_release; # apex # introduced=1
- stats_event_set_atom_id; # apex # introduced=1
- stats_event_write_int32; # apex # introduced=1
- stats_event_write_int64; # apex # introduced=1
- stats_event_write_float; # apex # introduced=1
- stats_event_write_bool; # apex # introduced=1
- stats_event_write_byte_array; # apex # introduced=1
- stats_event_write_string8; # apex # introduced=1
- stats_event_write_attribution_chain; # apex # introduced=1
- stats_event_write_key_value_pairs; # apex # introduced=1
- stats_event_add_bool_annotation; # apex # introduced=1
- stats_event_add_int32_annotation; # apex # introduced=1
- stats_event_get_atom_id; # apex # introduced=1
- stats_event_get_buffer; # apex # introduced=1
- stats_event_get_errors; # apex # introduced=1
+ AStatsEvent_obtain; # apex # introduced=30
+ AStatsEvent_build; # apex # introduced=30
+ AStatsEvent_write; # apex # introduced=30
+ AStatsEvent_release; # apex # introduced=30
+ AStatsEvent_setAtomId; # apex # introduced=30
+ AStatsEvent_writeInt32; # apex # introduced=30
+ AStatsEvent_writeInt64; # apex # introduced=30
+ AStatsEvent_writeFloat; # apex # introduced=30
+ AStatsEvent_writeBool; # apex # introduced=30
+ AStatsEvent_writeByteArray; # apex # introduced=30
+ AStatsEvent_writeString; # apex # introduced=30
+ AStatsEvent_writeAttributionChain; # apex # introduced=30
+ AStatsEvent_addBoolAnnotation; # apex # introduced=30
+ AStatsEvent_addInt32Annotation; # apex # introduced=30
local:
*;
};
diff --git a/libstats/socket/stats_event.c b/libstats/socket/stats_event.c
index 15039c6..5f77558 100644
--- a/libstats/socket/stats_event.c
+++ b/libstats/socket/stats_event.c
@@ -35,9 +35,36 @@
#define MAX_ANNOTATION_COUNT 15
#define MAX_BYTE_VALUE 127 // parsing side requires that lengths fit in 7 bits
-// The stats_event struct holds the serialized encoding of an event
+/* ERRORS */
+#define ERROR_NO_TIMESTAMP 0x1
+#define ERROR_NO_ATOM_ID 0x2
+#define ERROR_OVERFLOW 0x4
+#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
+#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
+#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
+#define ERROR_INVALID_ANNOTATION_ID 0x40
+#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
+#define ERROR_TOO_MANY_ANNOTATIONS 0x100
+#define ERROR_TOO_MANY_FIELDS 0x200
+#define ERROR_INVALID_VALUE_TYPE 0x400
+#define ERROR_STRING_NOT_NULL_TERMINATED 0x800
+
+/* TYPE IDS */
+#define INT32_TYPE 0x00
+#define INT64_TYPE 0x01
+#define STRING_TYPE 0x02
+#define LIST_TYPE 0x03
+#define FLOAT_TYPE 0x04
+#define BOOL_TYPE 0x05
+#define BYTE_ARRAY_TYPE 0x06
+#define OBJECT_TYPE 0x07
+#define KEY_VALUE_PAIRS_TYPE 0x08
+#define ATTRIBUTION_CHAIN_TYPE 0x09
+#define ERROR_TYPE 0x0F
+
+// The AStatsEvent struct holds the serialized encoding of an event
// within a buf. Also includes other required fields.
-struct stats_event {
+struct AStatsEvent {
uint8_t* buf;
size_t lastFieldPos; // location of last field within the buf
size_t size; // number of valid bytes within buffer
@@ -55,8 +82,8 @@
return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec;
}
-struct stats_event* stats_event_obtain() {
- struct stats_event* event = malloc(sizeof(struct stats_event));
+AStatsEvent* AStatsEvent_obtain() {
+ AStatsEvent* event = malloc(sizeof(AStatsEvent));
event->buf = (uint8_t*)calloc(MAX_EVENT_PAYLOAD, 1);
event->buf[0] = OBJECT_TYPE;
event->atomId = 0;
@@ -76,12 +103,12 @@
return event;
}
-void stats_event_release(struct stats_event* event) {
+void AStatsEvent_release(AStatsEvent* event) {
free(event->buf);
free(event);
}
-void stats_event_set_atom_id(struct stats_event* event, uint32_t atomId) {
+void AStatsEvent_setAtomId(AStatsEvent* event, uint32_t atomId) {
event->atomId = atomId;
event->buf[POS_ATOM_ID] = INT32_TYPE;
memcpy(&event->buf[POS_ATOM_ID + sizeof(uint8_t)], &atomId, sizeof(atomId));
@@ -89,7 +116,7 @@
}
// Side-effect: modifies event->errors if the buffer would overflow
-static bool overflows(struct stats_event* event, size_t size) {
+static bool overflows(AStatsEvent* event, size_t size) {
if (event->size + size > MAX_EVENT_PAYLOAD) {
event->errors |= ERROR_OVERFLOW;
return true;
@@ -99,39 +126,39 @@
// Side-effect: all append functions increment event->size if there is
// sufficient space within the buffer to place the value
-static void append_byte(struct stats_event* event, uint8_t value) {
+static void append_byte(AStatsEvent* event, uint8_t value) {
if (!overflows(event, sizeof(value))) {
event->buf[event->size] = value;
event->size += sizeof(value);
}
}
-static void append_bool(struct stats_event* event, bool value) {
+static void append_bool(AStatsEvent* event, bool value) {
append_byte(event, (uint8_t)value);
}
-static void append_int32(struct stats_event* event, int32_t value) {
+static void append_int32(AStatsEvent* event, int32_t value) {
if (!overflows(event, sizeof(value))) {
memcpy(&event->buf[event->size], &value, sizeof(value));
event->size += sizeof(value);
}
}
-static void append_int64(struct stats_event* event, int64_t value) {
+static void append_int64(AStatsEvent* event, int64_t value) {
if (!overflows(event, sizeof(value))) {
memcpy(&event->buf[event->size], &value, sizeof(value));
event->size += sizeof(value);
}
}
-static void append_float(struct stats_event* event, float value) {
+static void append_float(AStatsEvent* event, float value) {
if (!overflows(event, sizeof(value))) {
memcpy(&event->buf[event->size], &value, sizeof(value));
event->size += sizeof(float);
}
}
-static void append_byte_array(struct stats_event* event, const uint8_t* buf, size_t size) {
+static void append_byte_array(AStatsEvent* event, const uint8_t* buf, size_t size) {
if (!overflows(event, size)) {
memcpy(&event->buf[event->size], buf, size);
event->size += size;
@@ -139,7 +166,7 @@
}
// Side-effect: modifies event->errors if buf is not properly null-terminated
-static void append_string(struct stats_event* event, const char* buf) {
+static void append_string(AStatsEvent* event, const char* buf) {
size_t size = strnlen(buf, MAX_EVENT_PAYLOAD);
if (size == MAX_EVENT_PAYLOAD) {
event->errors |= ERROR_STRING_NOT_NULL_TERMINATED;
@@ -150,41 +177,41 @@
append_byte_array(event, (uint8_t*)buf, size);
}
-static void start_field(struct stats_event* event, uint8_t typeId) {
+static void start_field(AStatsEvent* event, uint8_t typeId) {
event->lastFieldPos = event->size;
append_byte(event, typeId);
event->numElements++;
}
-void stats_event_write_int32(struct stats_event* event, int32_t value) {
+void AStatsEvent_writeInt32(AStatsEvent* event, int32_t value) {
if (event->errors) return;
start_field(event, INT32_TYPE);
append_int32(event, value);
}
-void stats_event_write_int64(struct stats_event* event, int64_t value) {
+void AStatsEvent_writeInt64(AStatsEvent* event, int64_t value) {
if (event->errors) return;
start_field(event, INT64_TYPE);
append_int64(event, value);
}
-void stats_event_write_float(struct stats_event* event, float value) {
+void AStatsEvent_writeFloat(AStatsEvent* event, float value) {
if (event->errors) return;
start_field(event, FLOAT_TYPE);
append_float(event, value);
}
-void stats_event_write_bool(struct stats_event* event, bool value) {
+void AStatsEvent_writeBool(AStatsEvent* event, bool value) {
if (event->errors) return;
start_field(event, BOOL_TYPE);
append_bool(event, value);
}
-void stats_event_write_byte_array(struct stats_event* event, const uint8_t* buf, size_t numBytes) {
+void AStatsEvent_writeByteArray(AStatsEvent* event, const uint8_t* buf, size_t numBytes) {
if (event->errors) return;
start_field(event, BYTE_ARRAY_TYPE);
@@ -193,7 +220,7 @@
}
// Value is assumed to be encoded using UTF8
-void stats_event_write_string8(struct stats_event* event, const char* value) {
+void AStatsEvent_writeString(AStatsEvent* event, const char* value) {
if (event->errors) return;
start_field(event, STRING_TYPE);
@@ -201,8 +228,8 @@
}
// Tags are assumed to be encoded using UTF8
-void stats_event_write_attribution_chain(struct stats_event* event, const uint32_t* uids,
- const char* const* tags, uint8_t numNodes) {
+void AStatsEvent_writeAttributionChain(AStatsEvent* event, const uint32_t* uids,
+ const char* const* tags, uint8_t numNodes) {
if (numNodes > MAX_BYTE_VALUE) event->errors |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG;
if (event->errors) return;
@@ -215,39 +242,8 @@
}
}
-void stats_event_write_key_value_pairs(struct stats_event* event, struct key_value_pair* pairs,
- uint8_t numPairs) {
- if (numPairs > MAX_BYTE_VALUE) event->errors |= ERROR_TOO_MANY_KEY_VALUE_PAIRS;
- if (event->errors) return;
-
- start_field(event, KEY_VALUE_PAIRS_TYPE);
- append_byte(event, numPairs);
-
- for (uint8_t i = 0; i < numPairs; i++) {
- append_int32(event, pairs[i].key);
- append_byte(event, pairs[i].valueType);
- switch (pairs[i].valueType) {
- case INT32_TYPE:
- append_int32(event, pairs[i].int32Value);
- break;
- case INT64_TYPE:
- append_int64(event, pairs[i].int64Value);
- break;
- case FLOAT_TYPE:
- append_float(event, pairs[i].floatValue);
- break;
- case STRING_TYPE:
- append_string(event, pairs[i].stringValue);
- break;
- default:
- event->errors |= ERROR_INVALID_VALUE_TYPE;
- return;
- }
- }
-}
-
// Side-effect: modifies event->errors if field has too many annotations
-static void increment_annotation_count(struct stats_event* event) {
+static void increment_annotation_count(AStatsEvent* event) {
uint8_t fieldType = event->buf[event->lastFieldPos] & 0x0F;
uint32_t oldAnnotationCount = (event->buf[event->lastFieldPos] & 0xF0) >> 4;
uint32_t newAnnotationCount = oldAnnotationCount + 1;
@@ -260,7 +256,7 @@
event->buf[event->lastFieldPos] = (((uint8_t)newAnnotationCount << 4) & 0xF0) | fieldType;
}
-void stats_event_add_bool_annotation(struct stats_event* event, uint8_t annotationId, bool value) {
+void AStatsEvent_addBoolAnnotation(AStatsEvent* event, uint8_t annotationId, bool value) {
if (event->lastFieldPos == 0) event->errors |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
if (annotationId > MAX_BYTE_VALUE) event->errors |= ERROR_ANNOTATION_ID_TOO_LARGE;
if (event->errors) return;
@@ -271,8 +267,7 @@
increment_annotation_count(event);
}
-void stats_event_add_int32_annotation(struct stats_event* event, uint8_t annotationId,
- int32_t value) {
+void AStatsEvent_addInt32Annotation(AStatsEvent* event, uint8_t annotationId, int32_t value) {
if (event->lastFieldPos == 0) event->errors |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
if (annotationId > MAX_BYTE_VALUE) event->errors |= ERROR_ANNOTATION_ID_TOO_LARGE;
if (event->errors) return;
@@ -283,24 +278,24 @@
increment_annotation_count(event);
}
-uint32_t stats_event_get_atom_id(struct stats_event* event) {
+uint32_t AStatsEvent_getAtomId(AStatsEvent* event) {
return event->atomId;
}
-uint8_t* stats_event_get_buffer(struct stats_event* event, size_t* size) {
+uint8_t* AStatsEvent_getBuffer(AStatsEvent* event, size_t* size) {
if (size) *size = event->size;
return event->buf;
}
-uint32_t stats_event_get_errors(struct stats_event* event) {
+uint32_t AStatsEvent_getErrors(AStatsEvent* event) {
return event->errors;
}
-void stats_event_truncate_buffer(struct stats_event* event, bool truncate) {
+void AStatsEvent_truncateBuffer(AStatsEvent* event, bool truncate) {
event->truncate = truncate;
}
-void stats_event_build(struct stats_event* event) {
+void AStatsEvent_build(AStatsEvent* event) {
if (event->built) return;
if (event->atomId == 0) event->errors |= ERROR_NO_ATOM_ID;
@@ -327,28 +322,7 @@
event->built = true;
}
-int stats_event_write(struct stats_event* event) {
- stats_event_build(event);
+int AStatsEvent_write(AStatsEvent* event) {
+ AStatsEvent_build(event);
return write_buffer_to_statsd(&event->buf, event->size, event->atomId);
-}
-
-struct stats_event_api_table table = {
- stats_event_obtain,
- stats_event_build,
- stats_event_write,
- stats_event_release,
- stats_event_set_atom_id,
- stats_event_write_int32,
- stats_event_write_int64,
- stats_event_write_float,
- stats_event_write_bool,
- stats_event_write_byte_array,
- stats_event_write_string8,
- stats_event_write_attribution_chain,
- stats_event_write_key_value_pairs,
- stats_event_add_bool_annotation,
- stats_event_add_int32_annotation,
- stats_event_get_atom_id,
- stats_event_get_buffer,
- stats_event_get_errors,
-};
+}
\ No newline at end of file
diff --git a/libstats/socket/tests/stats_event_test.cpp b/libstats/socket/tests/stats_event_test.cpp
index cf0592c..48bf4b8 100644
--- a/libstats/socket/tests/stats_event_test.cpp
+++ b/libstats/socket/tests/stats_event_test.cpp
@@ -18,6 +18,34 @@
#include <gtest/gtest.h>
#include <utils/SystemClock.h>
+// Keep in sync stats_event.c. Consider moving to separate header file to avoid duplication.
+/* ERRORS */
+#define ERROR_NO_TIMESTAMP 0x1
+#define ERROR_NO_ATOM_ID 0x2
+#define ERROR_OVERFLOW 0x4
+#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
+#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
+#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
+#define ERROR_INVALID_ANNOTATION_ID 0x40
+#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
+#define ERROR_TOO_MANY_ANNOTATIONS 0x100
+#define ERROR_TOO_MANY_FIELDS 0x200
+#define ERROR_INVALID_VALUE_TYPE 0x400
+#define ERROR_STRING_NOT_NULL_TERMINATED 0x800
+
+/* TYPE IDS */
+#define INT32_TYPE 0x00
+#define INT64_TYPE 0x01
+#define STRING_TYPE 0x02
+#define LIST_TYPE 0x03
+#define FLOAT_TYPE 0x04
+#define BOOL_TYPE 0x05
+#define BYTE_ARRAY_TYPE 0x06
+#define OBJECT_TYPE 0x07
+#define KEY_VALUE_PAIRS_TYPE 0x08
+#define ATTRIBUTION_CHAIN_TYPE 0x09
+#define ERROR_TYPE 0x0F
+
using std::string;
using std::vector;
@@ -88,17 +116,17 @@
bool boolValue = false;
int64_t startTime = android::elapsedRealtimeNano();
- struct stats_event* event = stats_event_obtain();
- stats_event_set_atom_id(event, atomId);
- stats_event_write_int32(event, int32Value);
- stats_event_write_int64(event, int64Value);
- stats_event_write_float(event, floatValue);
- stats_event_write_bool(event, boolValue);
- stats_event_build(event);
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, atomId);
+ AStatsEvent_writeInt32(event, int32Value);
+ AStatsEvent_writeInt64(event, int64Value);
+ AStatsEvent_writeFloat(event, floatValue);
+ AStatsEvent_writeBool(event, boolValue);
+ AStatsEvent_build(event);
int64_t endTime = android::elapsedRealtimeNano();
size_t bufferSize;
- uint8_t* buffer = stats_event_get_buffer(event, &bufferSize);
+ uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
uint8_t* bufferEnd = buffer + bufferSize;
checkMetadata(&buffer, /*numElements=*/4, startTime, endTime, atomId);
@@ -120,8 +148,8 @@
checkScalar(&buffer, boolValue);
EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(stats_event_get_errors(event), 0);
- stats_event_release(event);
+ EXPECT_EQ(AStatsEvent_getErrors(event), 0);
+ AStatsEvent_release(event);
}
TEST(StatsEventTest, TestStrings) {
@@ -129,14 +157,14 @@
string str = "test_string";
int64_t startTime = android::elapsedRealtimeNano();
- struct stats_event* event = stats_event_obtain();
- stats_event_set_atom_id(event, atomId);
- stats_event_write_string8(event, str.c_str());
- stats_event_build(event);
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, atomId);
+ AStatsEvent_writeString(event, str.c_str());
+ AStatsEvent_build(event);
int64_t endTime = android::elapsedRealtimeNano();
size_t bufferSize;
- uint8_t* buffer = stats_event_get_buffer(event, &bufferSize);
+ uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
uint8_t* bufferEnd = buffer + bufferSize;
checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
@@ -145,8 +173,8 @@
checkString(&buffer, str);
EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(stats_event_get_errors(event), 0);
- stats_event_release(event);
+ EXPECT_EQ(AStatsEvent_getErrors(event), 0);
+ AStatsEvent_release(event);
}
TEST(StatsEventTest, TestByteArrays) {
@@ -154,14 +182,14 @@
vector<uint8_t> message = {'b', 'y', 't', '\0', 'e', 's'};
int64_t startTime = android::elapsedRealtimeNano();
- struct stats_event* event = stats_event_obtain();
- stats_event_set_atom_id(event, atomId);
- stats_event_write_byte_array(event, message.data(), message.size());
- stats_event_build(event);
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, atomId);
+ AStatsEvent_writeByteArray(event, message.data(), message.size());
+ AStatsEvent_build(event);
int64_t endTime = android::elapsedRealtimeNano();
size_t bufferSize;
- uint8_t* buffer = stats_event_get_buffer(event, &bufferSize);
+ uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
uint8_t* bufferEnd = buffer + bufferSize;
checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
@@ -170,8 +198,8 @@
checkByteArray(&buffer, message);
EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(stats_event_get_errors(event), 0);
- stats_event_release(event);
+ EXPECT_EQ(AStatsEvent_getErrors(event), 0);
+ AStatsEvent_release(event);
}
TEST(StatsEventTest, TestAttributionChains) {
@@ -188,14 +216,14 @@
}
int64_t startTime = android::elapsedRealtimeNano();
- struct stats_event* event = stats_event_obtain();
- stats_event_set_atom_id(event, atomId);
- stats_event_write_attribution_chain(event, uids, cTags, numNodes);
- stats_event_build(event);
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, atomId);
+ AStatsEvent_writeAttributionChain(event, uids, cTags, numNodes);
+ AStatsEvent_build(event);
int64_t endTime = android::elapsedRealtimeNano();
size_t bufferSize;
- uint8_t* buffer = stats_event_get_buffer(event, &bufferSize);
+ uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
uint8_t* bufferEnd = buffer + bufferSize;
checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
@@ -208,60 +236,8 @@
}
EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(stats_event_get_errors(event), 0);
- stats_event_release(event);
-}
-
-TEST(StatsEventTest, TestKeyValuePairs) {
- uint32_t atomId = 100;
-
- uint8_t numPairs = 4;
- struct key_value_pair pairs[numPairs];
- pairs[0] = {.key = 0, .valueType = INT32_TYPE, .int32Value = -1};
- pairs[1] = {.key = 1, .valueType = INT64_TYPE, .int64Value = 0x123456789};
- pairs[2] = {.key = 2, .valueType = FLOAT_TYPE, .floatValue = 5.5};
- string str = "test_key_value_pair_string";
- pairs[3] = {.key = 3, .valueType = STRING_TYPE, .stringValue = str.c_str()};
-
- int64_t startTime = android::elapsedRealtimeNano();
- struct stats_event* event = stats_event_obtain();
- stats_event_set_atom_id(event, atomId);
- stats_event_write_key_value_pairs(event, pairs, numPairs);
- stats_event_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = stats_event_get_buffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
-
- checkTypeHeader(&buffer, KEY_VALUE_PAIRS_TYPE);
- checkScalar(&buffer, numPairs);
-
- // first pair
- checkScalar(&buffer, pairs[0].key);
- checkTypeHeader(&buffer, pairs[0].valueType);
- checkScalar(&buffer, pairs[0].int32Value);
-
- // second pair
- checkScalar(&buffer, pairs[1].key);
- checkTypeHeader(&buffer, pairs[1].valueType);
- checkScalar(&buffer, pairs[1].int64Value);
-
- // third pair
- checkScalar(&buffer, pairs[2].key);
- checkTypeHeader(&buffer, pairs[2].valueType);
- checkScalar(&buffer, pairs[2].floatValue);
-
- // fourth pair
- checkScalar(&buffer, pairs[3].key);
- checkTypeHeader(&buffer, pairs[3].valueType);
- checkString(&buffer, str);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(stats_event_get_errors(event), 0);
- stats_event_release(event);
+ EXPECT_EQ(AStatsEvent_getErrors(event), 0);
+ AStatsEvent_release(event);
}
TEST(StatsEventTest, TestAnnotations) {
@@ -282,19 +258,19 @@
bool floatAnnotation2Value = false;
int64_t startTime = android::elapsedRealtimeNano();
- struct stats_event* event = stats_event_obtain();
- stats_event_set_atom_id(event, 100);
- stats_event_write_bool(event, boolValue);
- stats_event_add_bool_annotation(event, boolAnnotation1Id, boolAnnotation1Value);
- stats_event_add_int32_annotation(event, boolAnnotation2Id, boolAnnotation2Value);
- stats_event_write_float(event, floatValue);
- stats_event_add_int32_annotation(event, floatAnnotation1Id, floatAnnotation1Value);
- stats_event_add_bool_annotation(event, floatAnnotation2Id, floatAnnotation2Value);
- stats_event_build(event);
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
+ AStatsEvent_writeBool(event, boolValue);
+ AStatsEvent_addBoolAnnotation(event, boolAnnotation1Id, boolAnnotation1Value);
+ AStatsEvent_addInt32Annotation(event, boolAnnotation2Id, boolAnnotation2Value);
+ AStatsEvent_writeFloat(event, floatValue);
+ AStatsEvent_addInt32Annotation(event, floatAnnotation1Id, floatAnnotation1Value);
+ AStatsEvent_addBoolAnnotation(event, floatAnnotation2Id, floatAnnotation2Value);
+ AStatsEvent_build(event);
int64_t endTime = android::elapsedRealtimeNano();
size_t bufferSize;
- uint8_t* buffer = stats_event_get_buffer(event, &bufferSize);
+ uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
uint8_t* bufferEnd = buffer + bufferSize;
checkMetadata(&buffer, /*numElements=*/2, startTime, endTime, atomId);
@@ -312,33 +288,33 @@
checkAnnotation(&buffer, floatAnnotation2Id, BOOL_TYPE, floatAnnotation2Value);
EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(stats_event_get_errors(event), 0);
- stats_event_release(event);
+ EXPECT_EQ(AStatsEvent_getErrors(event), 0);
+ AStatsEvent_release(event);
}
TEST(StatsEventTest, TestNoAtomIdError) {
- struct stats_event* event = stats_event_obtain();
+ AStatsEvent* event = AStatsEvent_obtain();
// Don't set the atom id in order to trigger the error.
- stats_event_build(event);
+ AStatsEvent_build(event);
- uint32_t errors = stats_event_get_errors(event);
+ uint32_t errors = AStatsEvent_getErrors(event);
EXPECT_NE(errors | ERROR_NO_ATOM_ID, 0);
- stats_event_release(event);
+ AStatsEvent_release(event);
}
TEST(StatsEventTest, TestOverflowError) {
- struct stats_event* event = stats_event_obtain();
- stats_event_set_atom_id(event, 100);
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
// Add 1000 int32s to the event. Each int32 takes 5 bytes so this will
// overflow the 4068 byte buffer.
for (int i = 0; i < 1000; i++) {
- stats_event_write_int32(event, 0);
+ AStatsEvent_writeInt32(event, 0);
}
- stats_event_build(event);
+ AStatsEvent_build(event);
- uint32_t errors = stats_event_get_errors(event);
+ uint32_t errors = AStatsEvent_getErrors(event);
EXPECT_NE(errors | ERROR_OVERFLOW, 0);
- stats_event_release(event);
+ AStatsEvent_release(event);
}