Remove finalized concept from media.metrics
the 'finalized' concept didn't pan out -- remove references to it.
Simplifies the code flow.
Also purged some uses of generateSessionID().
Bug: 71874686
Test: logcat/dumpsys
Change-Id: I39e48526a5696158d8195f47154881ca6ecda266
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index a132e25..6d84a42 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -100,9 +100,6 @@
mDumpProtoDefault(MediaAnalyticsItem::PROTO_V1) {
ALOGD("MediaAnalyticsService created");
- // clear our queues
- mOpen = new List<MediaAnalyticsItem *>();
- mFinalized = new List<MediaAnalyticsItem *>();
mItemsSubmitted = 0;
mItemsFinalized = 0;
@@ -118,26 +115,13 @@
MediaAnalyticsService::~MediaAnalyticsService() {
ALOGD("MediaAnalyticsService destroyed");
- // clean out mOpen and mFinalized
- while (mOpen->size() > 0) {
- MediaAnalyticsItem * oitem = *(mOpen->begin());
- mOpen->erase(mOpen->begin());
+ while (mItems.size() > 0) {
+ MediaAnalyticsItem * oitem = *(mItems.begin());
+ mItems.erase(mItems.begin());
delete oitem;
mItemsDiscarded++;
mItemsDiscardedCount++;
}
- delete mOpen;
- mOpen = NULL;
-
- while (mFinalized->size() > 0) {
- MediaAnalyticsItem * oitem = *(mFinalized->begin());
- mFinalized->erase(mFinalized->begin());
- delete oitem;
- mItemsDiscarded++;
- mItemsDiscardedCount++;
- }
- delete mFinalized;
- mFinalized = NULL;
}
@@ -149,9 +133,14 @@
}
// caller surrenders ownership of 'item'
-MediaAnalyticsItem::SessionID_t MediaAnalyticsService::submit(MediaAnalyticsItem *item, bool forcenew) {
+MediaAnalyticsItem::SessionID_t MediaAnalyticsService::submit(MediaAnalyticsItem *item, bool forcenew)
+{
+ UNUSED(forcenew);
- MediaAnalyticsItem::SessionID_t id = MediaAnalyticsItem::SessionIDInvalid;
+ // fill in a sessionID if we do not yet have one
+ if (item->getSessionID() <= MediaAnalyticsItem::SessionIDNone) {
+ item->setSessionID(generateUniqueSessionID());
+ }
// we control these, generally not trusting user input
nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
@@ -164,9 +153,7 @@
int uid_given = item->getUid();
int pid_given = item->getPid();
- // although we do make exceptions for particular client uids
- // that we know we trust.
- //
+ // although we do make exceptions for some trusted client uids
bool isTrusted = false;
ALOGV("caller has uid=%d, embedded uid=%d", uid, uid_given);
@@ -192,7 +179,6 @@
break;
}
-
// Overwrite package name and version if the caller was untrusted.
if (!isTrusted) {
setPkgInfo(item, item->getUid(), true, true);
@@ -217,75 +203,23 @@
return MediaAnalyticsItem::SessionIDInvalid;
}
-
- // if we have a sesisonid in the new record, look to make
+ // XXX: if we have a sessionid in the new record, look to make
// sure it doesn't appear in the finalized list.
// XXX: this is for security / DOS prevention.
// may also require that we persist the unique sessionIDs
// across boots [instead of within a single boot]
-
- // match this new record up against records in the open
- // list...
- // if there's a match, merge them together
- // deal with moving the old / merged record into the finalized que
-
- bool finalizing = item->getFinalized();
-
- Mutex::Autolock _l(mLock);
-
- // if finalizing, we'll remove it
- MediaAnalyticsItem *oitem = findItem(mOpen, item, finalizing | forcenew);
- if (oitem != NULL) {
- if (forcenew) {
- // old one gets finalized, then we insert the new one
- // so we'll have 2 records at the end of this.
- // but don't finalize an empty record
- if (oitem->count() == 0) {
- // we're responsible for disposing of the dead record
- delete oitem;
- oitem = NULL;
- } else {
- oitem->setFinalized(true);
- saveItem(mFinalized, oitem, 0);
- }
- // new record could itself be marked finalized...
- id = item->getSessionID();
- if (finalizing) {
- saveItem(mFinalized, item, 0);
- mItemsFinalized++;
- } else {
- saveItem(mOpen, item, 1);
- }
- } else {
- // combine the records, send it to finalized if appropriate
- oitem->merge(item);
- id = oitem->getSessionID();
- if (finalizing) {
- saveItem(mFinalized, oitem, 0);
- mItemsFinalized++;
- }
-
- // we're responsible for disposing of the dead record
- delete item;
- item = NULL;
- }
- } else {
- // nothing to merge, save the new record
- id = item->getSessionID();
- if (finalizing) {
- if (item->count() == 0) {
- // drop empty records
- delete item;
- item = NULL;
- } else {
- saveItem(mFinalized, item, 0);
- mItemsFinalized++;
- }
- } else {
- saveItem(mOpen, item, 1);
- }
+ if (item->count() == 0) {
+ // drop empty records
+ delete item;
+ item = NULL;
+ return MediaAnalyticsItem::SessionIDInvalid;
}
+
+ // save the new record
+ MediaAnalyticsItem::SessionID_t id = item->getSessionID();
+ saveItem(item);
+ mItemsFinalized++;
return id;
}
@@ -378,6 +312,7 @@
}
Mutex::Autolock _l(mLock);
+ // mutex between insertion and dumping the contents
mDumpProto = chosenProto;
@@ -392,9 +327,9 @@
if (clear) {
// remove everything from the finalized queue
- while (mFinalized->size() > 0) {
- MediaAnalyticsItem * oitem = *(mFinalized->begin());
- mFinalized->erase(mFinalized->begin());
+ while (mItems.size() > 0) {
+ MediaAnalyticsItem * oitem = *(mItems.begin());
+ mItems.erase(mItems.begin());
delete oitem;
mItemsDiscarded++;
}
@@ -408,7 +343,8 @@
}
// dump headers
-void MediaAnalyticsService::dumpHeaders(String8 &result, nsecs_t ts_since) {
+void MediaAnalyticsService::dumpHeaders(String8 &result, nsecs_t ts_since)
+{
const size_t SIZE = 512;
char buffer[SIZE];
@@ -425,7 +361,7 @@
snprintf(buffer, SIZE,
"Since Boot: Submissions: %8" PRId64
- " Finalizations: %8" PRId64 "\n",
+ " Accepted: %8" PRId64 "\n",
mItemsSubmitted, mItemsFinalized);
result.append(buffer);
snprintf(buffer, SIZE,
@@ -433,19 +369,17 @@
" (by Count: %" PRId64 " by Expiration: %" PRId64 ")\n",
mItemsDiscarded, mItemsDiscardedCount, mItemsDiscardedExpire);
result.append(buffer);
- snprintf(buffer, SIZE,
- "Summary Sets Discarded: %" PRId64 "\n", mSetsDiscarded);
- result.append(buffer);
if (ts_since != 0) {
snprintf(buffer, SIZE,
- "Dumping Queue entries more recent than: %" PRId64 "\n",
+ "Emitting Queue entries more recent than: %" PRId64 "\n",
(int64_t) ts_since);
result.append(buffer);
}
}
// the recent, detailed queues
-void MediaAnalyticsService::dumpRecent(String8 &result, nsecs_t ts_since, const char * only) {
+void MediaAnalyticsService::dumpRecent(String8 &result, nsecs_t ts_since, const char * only)
+{
const size_t SIZE = 512;
char buffer[SIZE];
@@ -456,30 +390,27 @@
// show the recently recorded records
snprintf(buffer, sizeof(buffer), "\nFinalized Metrics (oldest first):\n");
result.append(buffer);
- result.append(this->dumpQueue(mFinalized, ts_since, only));
-
- snprintf(buffer, sizeof(buffer), "\nIn-Progress Metrics (newest first):\n");
- result.append(buffer);
- result.append(this->dumpQueue(mOpen, ts_since, only));
+ result.append(this->dumpQueue(ts_since, only));
// show who is connected and injecting records?
// talk about # records fed to the 'readers'
// talk about # records we discarded, perhaps "discarded w/o reading" too
}
+
// caller has locked mLock...
-String8 MediaAnalyticsService::dumpQueue(List<MediaAnalyticsItem *> *theList) {
- return dumpQueue(theList, (nsecs_t) 0, NULL);
+String8 MediaAnalyticsService::dumpQueue() {
+ return dumpQueue((nsecs_t) 0, NULL);
}
-String8 MediaAnalyticsService::dumpQueue(List<MediaAnalyticsItem *> *theList, nsecs_t ts_since, const char * only) {
+String8 MediaAnalyticsService::dumpQueue(nsecs_t ts_since, const char * only) {
String8 result;
int slot = 0;
- if (theList->empty()) {
+ if (mItems.empty()) {
result.append("empty\n");
} else {
- List<MediaAnalyticsItem *>::iterator it = theList->begin();
- for (; it != theList->end(); it++) {
+ List<MediaAnalyticsItem *>::iterator it = mItems.begin();
+ for (; it != mItems.end(); it++) {
nsecs_t when = (*it)->getTimestamp();
if (when < ts_since) {
continue;
@@ -500,35 +431,25 @@
//
// Our Cheap in-core, non-persistent records management.
-// XXX: rewrite this to manage persistence, etc.
// insert appropriately into queue
-// caller should hold mLock
-void MediaAnalyticsService::saveItem(List<MediaAnalyticsItem *> *l, MediaAnalyticsItem * item, int front) {
+void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item)
+{
- if (front) {
- // for non-finalized stuff, since we expect to reference it again soon,
- // make it quicker to find (nearer the front of our list)
- l->push_front(item);
- } else {
- // for finalized records, which we want to dump 'in sequence order'
- l->push_back(item);
- }
+ Mutex::Autolock _l(mLock);
+ // mutex between insertion and dumping the contents
- // our reclaim process is for oldest-first queues
- if (front) {
- return;
- }
-
+ // we want to dump 'in FIFO order', so insert at the end
+ mItems.push_back(item);
// keep removing old records the front until we're in-bounds (count)
if (mMaxRecords > 0) {
- while (l->size() > (size_t) mMaxRecords) {
- MediaAnalyticsItem * oitem = *(l->begin());
+ while (mItems.size() > (size_t) mMaxRecords) {
+ MediaAnalyticsItem * oitem = *(mItems.begin());
if (oitem == item) {
break;
}
- l->erase(l->begin());
+ mItems.erase(mItems.begin());
delete oitem;
mItemsDiscarded++;
mItemsDiscardedCount++;
@@ -536,10 +457,11 @@
}
// 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
if (mMaxRecordAgeNs > 0) {
nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
- while (l->size() > 0) {
- MediaAnalyticsItem * oitem = *(l->begin());
+ while (mItems.size() > 0) {
+ MediaAnalyticsItem * oitem = *(mItems.begin());
nsecs_t when = oitem->getTimestamp();
if (oitem == item) {
break;
@@ -549,7 +471,7 @@
// this (and the rest) are recent enough to keep
break;
}
- l->erase(l->begin());
+ mItems.erase(mItems.begin());
delete oitem;
mItemsDiscarded++;
mItemsDiscardedExpire++;
@@ -557,79 +479,6 @@
}
}
-// are they alike enough that nitem can be folded into oitem?
-static bool compatibleItems(MediaAnalyticsItem * oitem, MediaAnalyticsItem * nitem) {
-
- // general safety
- if (nitem->getUid() != oitem->getUid()) {
- return false;
- }
- if (nitem->getPid() != oitem->getPid()) {
- return false;
- }
-
- // key -- needs to match
- if (nitem->getKey() == oitem->getKey()) {
- // still in the game.
- } else {
- return false;
- }
-
- // session id -- empty field in new is allowed
- MediaAnalyticsItem::SessionID_t osession = oitem->getSessionID();
- MediaAnalyticsItem::SessionID_t nsession = nitem->getSessionID();
- if (nsession != osession) {
- // incoming '0' matches value in osession
- if (nsession != 0) {
- return false;
- }
- }
-
- return true;
-}
-
-// find the incomplete record that this will overlay
-// caller should hold mLock
-MediaAnalyticsItem *MediaAnalyticsService::findItem(List<MediaAnalyticsItem*> *theList, MediaAnalyticsItem *nitem, bool removeit) {
- if (nitem == NULL) {
- return NULL;
- }
-
- MediaAnalyticsItem *item = NULL;
-
- for (List<MediaAnalyticsItem *>::iterator it = theList->begin();
- it != theList->end(); it++) {
- MediaAnalyticsItem *tmp = (*it);
-
- if (!compatibleItems(tmp, nitem)) {
- continue;
- }
-
- // we match! this is the one I want.
- if (removeit) {
- theList->erase(it);
- }
- item = tmp;
- break;
- }
- return item;
-}
-
-
-// delete the indicated record
-// caller should hold mLock
-void MediaAnalyticsService::deleteItem(List<MediaAnalyticsItem *> *l, MediaAnalyticsItem *item) {
-
- for (List<MediaAnalyticsItem *>::iterator it = l->begin();
- it != l->end(); it++) {
- if ((*it)->getSessionID() != item->getSessionID())
- continue;
- delete *it;
- l->erase(it);
- break;
- }
-}
-
static std::string allowedKeys[] =
{
"audiorecord",
@@ -676,7 +525,9 @@
#define PKG_EXPIRATION_NS (30*60*1000000000ll) // 30 minutes, in nsecs
// give me the package name, perhaps going to find it
-void MediaAnalyticsService::setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion) {
+// manages its own mutex operations internally
+void MediaAnalyticsService::setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion)
+{
ALOGV("asking for packagename to go with uid=%d", uid);
if (!setName && !setVersion) {
@@ -686,22 +537,26 @@
nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
struct UidToPkgMap mapping;
- mapping.uid = (-1);
+ mapping.uid = (uid_t)(-1);
- ssize_t i = mPkgMappings.indexOfKey(uid);
- if (i >= 0) {
- mapping = mPkgMappings.valueAt(i);
- ALOGV("Expiration? uid %d expiration %" PRId64 " now %" PRId64,
- uid, mapping.expiration, now);
- if (mapping.expiration < now) {
- // purge our current entry and re-query
- ALOGV("entry for uid %d expired, now= %" PRId64 "", uid, now);
- mPkgMappings.removeItemsAt(i, 1);
- // could cheat and use a goto back to the top of the routine.
- // a good compiler should recognize the local tail recursion...
- return setPkgInfo(item, uid, setName, setVersion);
+ {
+ Mutex::Autolock _l(mLock_mappings);
+ int i = mPkgMappings.indexOfKey(uid);
+ if (i >= 0) {
+ mapping = mPkgMappings.valueAt(i);
+ ALOGV("Expiration? uid %d expiration %" PRId64 " now %" PRId64,
+ uid, mapping.expiration, now);
+ if (mapping.expiration <= now) {
+ // purge the stale entry and fall into re-fetching
+ ALOGV("entry for uid %d expired, now= %" PRId64 "", uid, now);
+ mPkgMappings.removeItemsAt(i);
+ mapping.uid = (uid_t)(-1);
+ }
}
- } else {
+ }
+
+ // if we did not find it
+ if (mapping.uid == (uid_t)(-1)) {
std::string pkg;
std::string installer = "";
int64_t versionCode = 0;
@@ -711,7 +566,7 @@
pkg = pw->pw_name;
}
- // find the proper value -- should we cache this binder??
+ // find the proper value
sp<IBinder> binder = NULL;
sp<IServiceManager> sm = defaultServiceManager();