Loading services/mediaanalytics/MediaAnalyticsService.cpp +81 −13 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <sys/stat.h> #include <sys/time.h> #include <dirent.h> #include <pthread.h> #include <unistd.h> #include <string.h> Loading Loading @@ -80,11 +81,18 @@ namespace android { using namespace android::content::pm; // individual records kept in memory: age or count // age: <= 36 hours (1.5 days) // age: <= 28 hours (1 1/6 days) // count: hard limit of # records // (0 for either of these disables that threshold) static const nsecs_t kMaxRecordAgeNs = 36 * 3600 * (1000*1000*1000ll); static const int kMaxRecords = 0; // static constexpr nsecs_t kMaxRecordAgeNs = 28 * 3600 * (1000*1000*1000ll); static constexpr int kMaxRecords = 0; // max we expire in a single call, to constrain how long we hold the // mutex, which also constrains how long a client might wait. static constexpr int kMaxExpiredAtOnce = 50; // TODO: need to look at tuning kMaxRecords and friends for low-memory devices static const char *kServiceName = "media.metrics"; Loading @@ -96,6 +104,7 @@ void MediaAnalyticsService::instantiate() { MediaAnalyticsService::MediaAnalyticsService() : mMaxRecords(kMaxRecords), mMaxRecordAgeNs(kMaxRecordAgeNs), mMaxRecordsExpiredAtOnce(kMaxExpiredAtOnce), mDumpProto(MediaAnalyticsItem::PROTO_V1), mDumpProtoDefault(MediaAnalyticsItem::PROTO_V1) { Loading Loading @@ -432,23 +441,29 @@ String8 MediaAnalyticsService::dumpQueue(nsecs_t ts_since, const char * only) { // // Our Cheap in-core, non-persistent records management. // insert appropriately into queue void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item) { Mutex::Autolock _l(mLock); // mutex between insertion and dumping the contents // we want to dump 'in FIFO order', so insert at the end mItems.push_back(item); // we hold mLock when we get here // if item != NULL, it's the item we just inserted // true == more items eligible to be recovered bool MediaAnalyticsService::expirations_l(MediaAnalyticsItem *item) { bool more = false; int handled = 0; // keep removing old records the front until we're in-bounds (count) // since we invoke this with each insertion, it should be 0/1 iterations. if (mMaxRecords > 0) { while (mItems.size() > (size_t) mMaxRecords) { MediaAnalyticsItem * oitem = *(mItems.begin()); if (oitem == item) { break; } if (handled >= mMaxRecordsExpiredAtOnce) { // unlikely in this loop more = true; break; } handled++; mItems.erase(mItems.begin()); delete oitem; mItemsDiscarded++; Loading @@ -456,8 +471,8 @@ void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item) } } // keep removing old records the front until we're in-bounds (count) // NB: expired entries aren't removed until the next insertion, which could be a while // keep removing old records the front until we're in-bounds (age) // limited to mMaxRecordsExpiredAtOnce items per invocation. if (mMaxRecordAgeNs > 0) { nsecs_t now = systemTime(SYSTEM_TIME_REALTIME); while (mItems.size() > 0) { Loading @@ -471,12 +486,65 @@ void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item) // this (and the rest) are recent enough to keep break; } if (handled >= mMaxRecordsExpiredAtOnce) { // this represents "one too many"; tell caller there are // more to be reclaimed. more = true; break; } handled++; mItems.erase(mItems.begin()); delete oitem; mItemsDiscarded++; mItemsDiscardedExpire++; } } // we only indicate whether there's more to clean; // caller chooses whether to schedule further cleanup. return more; } // process expirations in bite sized chunks, allowing new insertions through // runs in a pthread specifically started for this (which then exits) bool MediaAnalyticsService::processExpirations() { bool more; do { sleep(1); { Mutex::Autolock _l(mLock); more = expirations_l(NULL); if (!more) { break; } } } while (more); return true; // value is for std::future thread synchronization } // insert appropriately into queue void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item) { Mutex::Autolock _l(mLock); // mutex between insertion and dumping the contents // we want to dump 'in FIFO order', so insert at the end mItems.push_back(item); // clean old stuff from the queue bool more = expirations_l(item); // consider scheduling some asynchronous cleaning, if not running if (more) { if (!mExpireFuture.valid() || mExpireFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { mExpireFuture = std::async(std::launch::async, [this]() {return this->processExpirations();}); } } } static std::string allowedKeys[] = Loading services/mediaanalytics/MediaAnalyticsService.h +9 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ #include <utils/String8.h> #include <utils/List.h> #include <future> #include <media/IMediaAnalyticsService.h> namespace android { Loading @@ -44,6 +46,8 @@ class MediaAnalyticsService : public BnMediaAnalyticsService MediaAnalyticsService(); virtual ~MediaAnalyticsService(); bool processExpirations(); private: MediaAnalyticsItem::SessionID_t generateUniqueSessionID(); Loading @@ -65,6 +69,8 @@ class MediaAnalyticsService : public BnMediaAnalyticsService int32_t mMaxRecords; // by time (none older than this long agan nsecs_t mMaxRecordAgeNs; // max to expire per expirations_l() invocation int32_t mMaxRecordsExpiredAtOnce; // // # of sets of summaries int32_t mMaxRecordSets; Loading @@ -79,6 +85,9 @@ class MediaAnalyticsService : public BnMediaAnalyticsService List<MediaAnalyticsItem *> mItems; void saveItem(MediaAnalyticsItem *); bool expirations_l(MediaAnalyticsItem *); std::future<bool> mExpireFuture; // support for generating output int mDumpProto; int mDumpProtoDefault; Loading Loading
services/mediaanalytics/MediaAnalyticsService.cpp +81 −13 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <sys/stat.h> #include <sys/time.h> #include <dirent.h> #include <pthread.h> #include <unistd.h> #include <string.h> Loading Loading @@ -80,11 +81,18 @@ namespace android { using namespace android::content::pm; // individual records kept in memory: age or count // age: <= 36 hours (1.5 days) // age: <= 28 hours (1 1/6 days) // count: hard limit of # records // (0 for either of these disables that threshold) static const nsecs_t kMaxRecordAgeNs = 36 * 3600 * (1000*1000*1000ll); static const int kMaxRecords = 0; // static constexpr nsecs_t kMaxRecordAgeNs = 28 * 3600 * (1000*1000*1000ll); static constexpr int kMaxRecords = 0; // max we expire in a single call, to constrain how long we hold the // mutex, which also constrains how long a client might wait. static constexpr int kMaxExpiredAtOnce = 50; // TODO: need to look at tuning kMaxRecords and friends for low-memory devices static const char *kServiceName = "media.metrics"; Loading @@ -96,6 +104,7 @@ void MediaAnalyticsService::instantiate() { MediaAnalyticsService::MediaAnalyticsService() : mMaxRecords(kMaxRecords), mMaxRecordAgeNs(kMaxRecordAgeNs), mMaxRecordsExpiredAtOnce(kMaxExpiredAtOnce), mDumpProto(MediaAnalyticsItem::PROTO_V1), mDumpProtoDefault(MediaAnalyticsItem::PROTO_V1) { Loading Loading @@ -432,23 +441,29 @@ String8 MediaAnalyticsService::dumpQueue(nsecs_t ts_since, const char * only) { // // Our Cheap in-core, non-persistent records management. // insert appropriately into queue void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item) { Mutex::Autolock _l(mLock); // mutex between insertion and dumping the contents // we want to dump 'in FIFO order', so insert at the end mItems.push_back(item); // we hold mLock when we get here // if item != NULL, it's the item we just inserted // true == more items eligible to be recovered bool MediaAnalyticsService::expirations_l(MediaAnalyticsItem *item) { bool more = false; int handled = 0; // keep removing old records the front until we're in-bounds (count) // since we invoke this with each insertion, it should be 0/1 iterations. if (mMaxRecords > 0) { while (mItems.size() > (size_t) mMaxRecords) { MediaAnalyticsItem * oitem = *(mItems.begin()); if (oitem == item) { break; } if (handled >= mMaxRecordsExpiredAtOnce) { // unlikely in this loop more = true; break; } handled++; mItems.erase(mItems.begin()); delete oitem; mItemsDiscarded++; Loading @@ -456,8 +471,8 @@ void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item) } } // keep removing old records the front until we're in-bounds (count) // NB: expired entries aren't removed until the next insertion, which could be a while // keep removing old records the front until we're in-bounds (age) // limited to mMaxRecordsExpiredAtOnce items per invocation. if (mMaxRecordAgeNs > 0) { nsecs_t now = systemTime(SYSTEM_TIME_REALTIME); while (mItems.size() > 0) { Loading @@ -471,12 +486,65 @@ void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item) // this (and the rest) are recent enough to keep break; } if (handled >= mMaxRecordsExpiredAtOnce) { // this represents "one too many"; tell caller there are // more to be reclaimed. more = true; break; } handled++; mItems.erase(mItems.begin()); delete oitem; mItemsDiscarded++; mItemsDiscardedExpire++; } } // we only indicate whether there's more to clean; // caller chooses whether to schedule further cleanup. return more; } // process expirations in bite sized chunks, allowing new insertions through // runs in a pthread specifically started for this (which then exits) bool MediaAnalyticsService::processExpirations() { bool more; do { sleep(1); { Mutex::Autolock _l(mLock); more = expirations_l(NULL); if (!more) { break; } } } while (more); return true; // value is for std::future thread synchronization } // insert appropriately into queue void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item) { Mutex::Autolock _l(mLock); // mutex between insertion and dumping the contents // we want to dump 'in FIFO order', so insert at the end mItems.push_back(item); // clean old stuff from the queue bool more = expirations_l(item); // consider scheduling some asynchronous cleaning, if not running if (more) { if (!mExpireFuture.valid() || mExpireFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { mExpireFuture = std::async(std::launch::async, [this]() {return this->processExpirations();}); } } } static std::string allowedKeys[] = Loading
services/mediaanalytics/MediaAnalyticsService.h +9 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ #include <utils/String8.h> #include <utils/List.h> #include <future> #include <media/IMediaAnalyticsService.h> namespace android { Loading @@ -44,6 +46,8 @@ class MediaAnalyticsService : public BnMediaAnalyticsService MediaAnalyticsService(); virtual ~MediaAnalyticsService(); bool processExpirations(); private: MediaAnalyticsItem::SessionID_t generateUniqueSessionID(); Loading @@ -65,6 +69,8 @@ class MediaAnalyticsService : public BnMediaAnalyticsService int32_t mMaxRecords; // by time (none older than this long agan nsecs_t mMaxRecordAgeNs; // max to expire per expirations_l() invocation int32_t mMaxRecordsExpiredAtOnce; // // # of sets of summaries int32_t mMaxRecordSets; Loading @@ -79,6 +85,9 @@ class MediaAnalyticsService : public BnMediaAnalyticsService List<MediaAnalyticsItem *> mItems; void saveItem(MediaAnalyticsItem *); bool expirations_l(MediaAnalyticsItem *); std::future<bool> mExpireFuture; // support for generating output int mDumpProto; int mDumpProtoDefault; Loading