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

Commit f49c38be authored by Howard Ro's avatar Howard Ro Committed by Android (Google) Code Review
Browse files

Merge "Expose libstatspull as a stable C API"

parents 4fe7fe72 a8fd39d8
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