Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8fd39d8 authored by Tej Singh's avatar Tej Singh
Browse files

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
parent 98027bf9
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ cc_library_shared {
    ],
    export_include_dirs: ["include"],
    shared_libs: [
        //TODO: use libbinder_ndk.
        //TODO: use libbinder_ndk. Remove libservices.
        "libbinder",
        "libstatssocket",
        "libservices",
@@ -40,5 +40,12 @@ cc_library_shared {
    static_libs: [
        "liblog",
        "libutils",
    ]
    ],
    // enumerate stable entry points for APEX use
    stubs: {
        symbol_file: "libstatspull.map.txt",
        versions: [
            "30",
        ],
    },
}
+100 −19
Original line number Diff line number Diff line
@@ -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
}
+13 −0
Original line number Diff line number Diff line
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:
        *;
};
+51 −16
Original line number Diff line number Diff line
@@ -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 @@ struct stats_event* add_stats_event_to_pull_data(pulled_stats_event_list* pull_d
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 @@ class StatsPullAtomCallbackInternal : public android::os::BnPullAtomCallback {
    ::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 @@ class StatsPullAtomCallbackInternal : public android::os::BnPullAtomCallback {

        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 @@ class StatsPullAtomCallbackInternal : public android::os::BnPullAtomCallback {
    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 @@ void unregisterStatsPullAtomCallbackBlocking(int32_t atomTag) {
    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 @@ void register_stats_pull_atom_callback(int32_t atom_tag, stats_pull_atom_callbac
    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.
+26 −37
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ const bool StatsEventCompat::mPlatformAtLeastR =

// 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 @@ StatsEventCompat::StatsEventCompat() : mEventQ(kStatsEventTag) {
        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 @@ StatsEventCompat::StatsEventCompat() : mEventQ(kStatsEventTag) {
    }

    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::setAtomId(int32_t atomId) {

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::writeInt32(int32_t value) {

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::writeInt64(int64_t value) {

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::writeFloat(float value) {

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::writeBool(bool value) {

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 @@ void StatsEventCompat::writeString(const char* value) {
    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::writeString(const char* value) {
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 @@ void StatsEventCompat::writeKeyValuePairs(const map<int, int32_t>& int32Map,
                                          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<float>(const map<int, float
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);
Loading