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

Commit 18511ee7 authored by Robert Shih's avatar Robert Shih Committed by Android (Google) Code Review
Browse files

Merge "mediametrics: implement AStatsManager_PullAtomCallback" into sc-dev

parents c471ed5d 2e15aede
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -165,10 +165,18 @@ cc_library {
        "libmediautils",
        "libmemunreachable",
        "libprotobuf-cpp-lite",
        "libstagefright_foundation",
        "libstatslog",
        "libstatspull",
        "libstatssocket",
        "libutils",
    ],

    export_shared_lib_headers: [
        "libstatspull",
        "libstatssocket",
    ],

    static_libs: [
        "libplatformprotos",
    ],
+61 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <utils/Log.h>

#include "MediaMetricsService.h"
#include "iface_statsd.h"

#include <pwd.h> //getpwuid

@@ -30,6 +31,9 @@
#include <mediautils/MemoryLeakTrackUtil.h>
#include <memunreachable/memunreachable.h>
#include <private/android_filesystem_config.h> // UID
#include <statslog.h>

#include <set>

namespace android {

@@ -200,7 +204,6 @@ status_t MediaMetricsService::submitInternal(mediametrics::Item *item, bool rele

    (void)mAudioAnalytics.submit(sitem, isTrusted);

    extern bool dump2Statsd(const std::shared_ptr<const mediametrics::Item>& item);
    (void)dump2Statsd(sitem);  // failure should be logged in function.
    saveItem(sitem);
    return NO_ERROR;
@@ -440,6 +443,10 @@ void MediaMetricsService::saveItem(const std::shared_ptr<const mediametrics::Ite
    std::lock_guard _l(mLock);
    // we assume the items are roughly in time order.
    mItems.emplace_back(item);
    if (isPullable(item->getKey())) {
        registerStatsdCallbacksIfNeeded();
        mPullableItems[item->getKey()].emplace_back(item);
    }
    ++mItemsFinalized;
    if (expirations(item)
            && (!mExpireFuture.valid()
@@ -486,4 +493,57 @@ bool MediaMetricsService::isRateLimited(mediametrics::Item *) const
    return false;
}

void MediaMetricsService::registerStatsdCallbacksIfNeeded()
{
    if (mStatsdRegistered.test_and_set()) {
        return;
    }
    auto tag = android::util::MEDIA_DRM_ACTIVITY_INFO;
    auto cb = MediaMetricsService::pullAtomCallback;
    AStatsManager_setPullAtomCallback(tag, /* metadata */ nullptr, cb, this);
}

/* static */
bool MediaMetricsService::isPullable(const std::string &key)
{
    static const std::set<std::string> pullableKeys{
        "mediadrm",
    };
    return pullableKeys.count(key);
}

/* static */
std::string MediaMetricsService::atomTagToKey(int32_t atomTag)
{
    switch (atomTag) {
    case android::util::MEDIA_DRM_ACTIVITY_INFO:
        return "mediadrm";
    }
    return {};
}

/* static */
AStatsManager_PullAtomCallbackReturn MediaMetricsService::pullAtomCallback(
        int32_t atomTag, AStatsEventList* data, void* cookie)
{
    MediaMetricsService* svc = reinterpret_cast<MediaMetricsService*>(cookie);
    return svc->pullItems(atomTag, data);
}

AStatsManager_PullAtomCallbackReturn MediaMetricsService::pullItems(
        int32_t atomTag, AStatsEventList* data)
{
    const std::string key(atomTagToKey(atomTag));
    if (key.empty()) {
        return AStatsManager_PULL_SKIP;
    }
    std::lock_guard _l(mLock);
    for (auto &item : mPullableItems[key]) {
        if (const auto sitem = item.lock()) {
            dump2Statsd(sitem, data);
        }
    }
    mPullableItems[key].clear();
    return AStatsManager_PULL_SUCCESS;
}
} // namespace android
+16 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <android-base/thread_annotations.h>
#include <android/media/BnMediaMetricsService.h>
#include <mediautils/ServiceUtilities.h>
#include <stats_pull_atom_callback.h>
#include <utils/String8.h>

#include "AudioAnalytics.h"
@@ -102,6 +103,15 @@ private:
    void dumpQueue(String8 &result, int64_t sinceNs, const char* prefix) REQUIRES(mLock);
    void dumpHeaders(String8 &result, int64_t sinceNs, const char* prefix) REQUIRES(mLock);

    // support statsd pushed atoms
    static bool isPullable(const std::string &key);
    static std::string atomTagToKey(int32_t atomTag);
    static AStatsManager_PullAtomCallbackReturn pullAtomCallback(
            int32_t atomTag, AStatsEventList* data, void* cookie);
    AStatsManager_PullAtomCallbackReturn pullItems(int32_t atomTag, AStatsEventList* data);
    void registerStatsdCallbacksIfNeeded();
    std::atomic_flag mStatsdRegistered = ATOMIC_FLAG_INIT;

    // The following variables accessed without mLock

    // limit how many records we'll retain
@@ -130,6 +140,12 @@ private:
    // TODO: Make separate class, use segmented queue, write lock only end.
    // Note: Another analytics module might have ownership of an item longer than the log.
    std::deque<std::shared_ptr<const mediametrics::Item>> mItems GUARDED_BY(mLock);

    // Queues per item key, pending to be pulled by statsd.
    // Use weak_ptr such that a pullable item can still expire.
    using ItemKey = std::string;
    using WeakItemQueue = std::deque<std::weak_ptr<const mediametrics::Item>>;
    std::unordered_map<ItemKey, WeakItemQueue> mPullableItems GUARDED_BY(mLock);
};

} // namespace android
+3 −0
Original line number Diff line number Diff line
@@ -50,7 +50,10 @@ cc_fuzz {
        "libmemunreachable",
        "libprotobuf-cpp-lite",
        "libstagefright",
        "libstagefright_foundation",
        "libstatslog",
        "libstatspull",
        "libstatssocket",
        "libutils",
        "mediametricsservice-aidl-cpp",
    ],
+41 −28
Original line number Diff line number Diff line
@@ -27,7 +27,10 @@
#include <pthread.h>
#include <unistd.h>

#include <map>
#include <memory>
#include <string>
#include <vector>
#include <string.h>
#include <pwd.h>

@@ -47,13 +50,33 @@ namespace android {

bool enabled_statsd = true;

struct statsd_hooks {
    const char *key;
    bool (*handler)(const mediametrics::Item *);
};
using statsd_pusher = bool (*)(const mediametrics::Item *);
using statsd_puller = bool (*)(const mediametrics::Item *, AStatsEventList *);

namespace {
template<typename Handler, typename... Args>
bool dump2StatsdInternal(const std::map<std::string, Handler>& handlers,
        const std::shared_ptr<const mediametrics::Item>& item, Args... args) {
    if (item == nullptr) return false;

    // get the key
    std::string key = item->getKey();

    if (!enabled_statsd) {
        ALOGV("statsd logging disabled for record key=%s", key.c_str());
        return false;
    }

    if (handlers.count(key)) {
        return (handlers.at(key))(item.get(), args...);
    }
    return false;
}
} // namespace

// keep this sorted, so we can do binary searches
static constexpr struct statsd_hooks statsd_handlers[] =
// give me a record, I'll look at the type and upload appropriately
bool dump2Statsd(const std::shared_ptr<const mediametrics::Item>& item) {
    static const std::map<std::string, statsd_pusher> statsd_pushers =
    {
        { "audiopolicy", statsd_audiopolicy },
        { "audiorecord", statsd_audiorecord },
@@ -68,25 +91,15 @@ static constexpr struct statsd_hooks statsd_handlers[] =
        { "nuplayer2", statsd_nuplayer },
        { "recorder", statsd_recorder },
    };

// give me a record, i'll look at the type and upload appropriately
bool dump2Statsd(const std::shared_ptr<const mediametrics::Item>& item) {
    if (item == nullptr) return false;

    // get the key
    std::string key = item->getKey();

    if (!enabled_statsd) {
        ALOGV("statsd logging disabled for record key=%s", key.c_str());
        return false;
    return dump2StatsdInternal(statsd_pushers, item);
}

    for (const auto &statsd_handler : statsd_handlers) {
        if (key == statsd_handler.key) {
            return statsd_handler.handler(item.get());
        }
    }
    return false;
bool dump2Statsd(const std::shared_ptr<const mediametrics::Item>& item, AStatsEventList* out) {
    static const std::map<std::string, statsd_puller> statsd_pullers =
    {
        { "mediadrm", statsd_mediadrm_puller },
    };
    return dump2StatsdInternal(statsd_pullers, item, out);
}

} // namespace android
Loading