Loading services/mediametrics/Android.bp +8 −0 Original line number Diff line number Diff line Loading @@ -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", ], Loading services/mediametrics/MediaMetricsService.cpp +61 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <utils/Log.h> #include "MediaMetricsService.h" #include "iface_statsd.h" #include <pwd.h> //getpwuid Loading @@ -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 { Loading Loading @@ -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; Loading Loading @@ -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() Loading Loading @@ -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 services/mediametrics/MediaMetricsService.h +16 −0 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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 Loading Loading @@ -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 services/mediametrics/fuzzer/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -50,7 +50,10 @@ cc_fuzz { "libmemunreachable", "libprotobuf-cpp-lite", "libstagefright", "libstagefright_foundation", "libstatslog", "libstatspull", "libstatssocket", "libutils", "mediametricsservice-aidl-cpp", ], Loading services/mediametrics/iface_statsd.cpp +41 −28 Original line number Diff line number Diff line Loading @@ -27,7 +27,10 @@ #include <pthread.h> #include <unistd.h> #include <map> #include <memory> #include <string> #include <vector> #include <string.h> #include <pwd.h> Loading @@ -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 }, Loading @@ -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
services/mediametrics/Android.bp +8 −0 Original line number Diff line number Diff line Loading @@ -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", ], Loading
services/mediametrics/MediaMetricsService.cpp +61 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <utils/Log.h> #include "MediaMetricsService.h" #include "iface_statsd.h" #include <pwd.h> //getpwuid Loading @@ -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 { Loading Loading @@ -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; Loading Loading @@ -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() Loading Loading @@ -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
services/mediametrics/MediaMetricsService.h +16 −0 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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 Loading Loading @@ -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
services/mediametrics/fuzzer/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -50,7 +50,10 @@ cc_fuzz { "libmemunreachable", "libprotobuf-cpp-lite", "libstagefright", "libstagefright_foundation", "libstatslog", "libstatspull", "libstatssocket", "libutils", "mediametricsservice-aidl-cpp", ], Loading
services/mediametrics/iface_statsd.cpp +41 −28 Original line number Diff line number Diff line Loading @@ -27,7 +27,10 @@ #include <pthread.h> #include <unistd.h> #include <map> #include <memory> #include <string> #include <vector> #include <string.h> #include <pwd.h> Loading @@ -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 }, Loading @@ -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