Expose libstatspull as a stable C API

Libstatspull will ship as a part of the statsd apex in R.

Also update libstatssocket to have version 30 to align with api level,
as per native api council feedback.

Change both libraries to use NDK style naming conventions (AStatsEvent,
AStatsManager), and remove unneeded APIs in libstatssocket.

Remove KeyValuePairs from libstatssocket. KeyValuePairs will not be
supported in native code.

Bug: 147499386
Test: make libstatspull
Test: make libstatssocket
Test: atest libstatssocket_test
Change-Id: Ie79771461215a057529aaac91db95e4334c3960e
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.