Loading services/mediaanalytics/MetricsSummarizer.cpp +98 −32 Original line number Diff line number Diff line Loading @@ -141,23 +141,23 @@ void MetricsSummarizer::handleRecord(MediaAnalyticsItem *item) { List<MediaAnalyticsItem *>::iterator it = mSummaries->begin(); for (; it != mSummaries->end(); it++) { bool good = sameAttributes((*it), item, getIgnorables()); ALOGV("Match against %s says %d", (*it)->toString().c_str(), good); ALOGV("Match against %s says %d", (*it)->toString().c_str(), good); if (good) break; } if (it == mSummaries->end()) { ALOGV("save new record"); item = item->dup(); if (item == NULL) { MediaAnalyticsItem *nitem = item->dup(); if (nitem == NULL) { ALOGE("unable to save MediaMetrics record"); } sortProps(item); item->setInt32("count",1); mSummaries->push_back(item); sortProps(nitem); nitem->setInt32("aggregated",1); mergeRecord(*nitem, *item); mSummaries->push_back(nitem); } else { ALOGV("increment existing record"); (*it)->addInt32("count",1); (*it)->addInt32("aggregated",1); mergeRecord(*(*it), *item); } } Loading @@ -168,6 +168,71 @@ void MetricsSummarizer::mergeRecord(MediaAnalyticsItem &/*have*/, MediaAnalytics return; } // keep some stats for things: sums, counts, standard deviation // the integer version -- all of these pieces are in 64 bits void MetricsSummarizer::minMaxVar64(MediaAnalyticsItem &summation, const char *key, int64_t value) { if (key == NULL) return; int len = strlen(key) + 32; char *tmpKey = (char *)malloc(len); if (tmpKey == NULL) { return; } // N - count of samples snprintf(tmpKey, len, "%s.n", key); summation.addInt64(tmpKey, 1); // zero - count of samples that are zero if (value == 0) { snprintf(tmpKey, len, "%s.zero", key); int64_t zero = 0; (void) summation.getInt64(tmpKey,&zero); zero++; summation.setInt64(tmpKey, zero); } // min snprintf(tmpKey, len, "%s.min", key); int64_t min = value; if (summation.getInt64(tmpKey,&min)) { if (min > value) { summation.setInt64(tmpKey, value); } } else { summation.setInt64(tmpKey, value); } // max snprintf(tmpKey, len, "%s.max", key); int64_t max = value; if (summation.getInt64(tmpKey,&max)) { if (max < value) { summation.setInt64(tmpKey, value); } } else { summation.setInt64(tmpKey, value); } // components for mean, stddev; // stddev = sqrt(1/4*(sumx2 - (2*sumx*sumx/n) + ((sumx/n)^2))) // sum x snprintf(tmpKey, len, "%s.sumX", key); summation.addInt64(tmpKey, value); // sum x^2 snprintf(tmpKey, len, "%s.sumX2", key); summation.addInt64(tmpKey, value*value); // last thing we do -- remove the base key from the summation // record so we won't get confused about it having both individual // and summary information in there. summation.removeProp(key); free(tmpKey); } // // Comparators Loading @@ -186,20 +251,23 @@ bool MetricsSummarizer::sameAttributes(MediaAnalyticsItem *summ, MediaAnalyticsI ALOGV("MetricsSummarizer::sameAttributes(): summ %s", summ->toString().c_str()); ALOGV("MetricsSummarizer::sameAttributes(): single %s", single->toString().c_str()); // keep different sources/users separate if (single->mUid != summ->mUid) { return false; } // this can be made better. for(size_t i=0;i<single->mPropCount;i++) { MediaAnalyticsItem::Prop *prop1 = &(single->mProps[i]); const char *attrName = prop1->mName; ALOGV("compare on attr '%s'", attrName); // is it something we should ignore if (ignorable != NULL) { const char **ig = ignorable; while (*ig) { for (;*ig; ig++) { if (strcmp(*ig, attrName) == 0) { break; } ig++; } if (*ig) { ALOGV("we don't mind that it has attr '%s'", attrName); Loading @@ -218,29 +286,42 @@ bool MetricsSummarizer::sameAttributes(MediaAnalyticsItem *summ, MediaAnalyticsI } switch (prop1->mType) { case MediaAnalyticsItem::kTypeInt32: if (prop1->u.int32Value != prop2->u.int32Value) if (prop1->u.int32Value != prop2->u.int32Value) { ALOGV("mismatch values"); return false; } break; case MediaAnalyticsItem::kTypeInt64: if (prop1->u.int64Value != prop2->u.int64Value) if (prop1->u.int64Value != prop2->u.int64Value) { ALOGV("mismatch values"); return false; } break; case MediaAnalyticsItem::kTypeDouble: // XXX: watch out for floating point comparisons! if (prop1->u.doubleValue != prop2->u.doubleValue) if (prop1->u.doubleValue != prop2->u.doubleValue) { ALOGV("mismatch values"); return false; } break; case MediaAnalyticsItem::kTypeCString: if (strcmp(prop1->u.CStringValue, prop2->u.CStringValue) != 0) if (strcmp(prop1->u.CStringValue, prop2->u.CStringValue) != 0) { ALOGV("mismatch values"); return false; } break; case MediaAnalyticsItem::kTypeRate: if (prop1->u.rate.count != prop2->u.rate.count) if (prop1->u.rate.count != prop2->u.rate.count) { ALOGV("mismatch values"); return false; if (prop1->u.rate.duration != prop2->u.rate.duration) } if (prop1->u.rate.duration != prop2->u.rate.duration) { ALOGV("mismatch values"); return false; } break; default: ALOGV("mismatch values in default type"); return false; } } Loading @@ -248,15 +329,6 @@ bool MetricsSummarizer::sameAttributes(MediaAnalyticsItem *summ, MediaAnalyticsI return true; } bool MetricsSummarizer::sameAttributesId(MediaAnalyticsItem *summ, MediaAnalyticsItem *single, const char **ignorable) { // verify same user if (summ->mPid != single->mPid) return false; // and finally do the more expensive validation of the attributes return sameAttributes(summ, single, ignorable); } int MetricsSummarizer::PropSorter(const void *a, const void *b) { MediaAnalyticsItem::Prop *ai = (MediaAnalyticsItem::Prop *)a; Loading @@ -267,14 +339,8 @@ int MetricsSummarizer::PropSorter(const void *a, const void *b) { // we sort in the summaries so that it looks pretty in the dumpsys void MetricsSummarizer::sortProps(MediaAnalyticsItem *item) { if (item->mPropCount != 0) { if (DEBUG_SORT) { ALOGD("sortProps(pre): %s", item->toString().c_str()); } qsort(item->mProps, item->mPropCount, sizeof(MediaAnalyticsItem::Prop), MetricsSummarizer::PropSorter); if (DEBUG_SORT) { ALOGD("sortProps(pst): %s", item->toString().c_str()); } } } Loading services/mediaanalytics/MetricsSummarizer.h +2 −3 Original line number Diff line number Diff line Loading @@ -59,10 +59,9 @@ class MetricsSummarizer // various comparators // "do these records have same attributes and values in those attrs" // ditto, but watch for "error" fields bool sameAttributes(MediaAnalyticsItem *summ, MediaAnalyticsItem *single, const char **ignoreables); // attributes + from the same app/userid bool sameAttributesId(MediaAnalyticsItem *summ, MediaAnalyticsItem *single, const char **ignoreables); void minMaxVar64(MediaAnalyticsItem &summ, const char *key, int64_t value); static int PropSorter(const void *a, const void *b); void sortProps(MediaAnalyticsItem *item); Loading services/mediaanalytics/MetricsSummarizerPlayer.cpp +23 −17 Original line number Diff line number Diff line Loading @@ -51,36 +51,42 @@ MetricsSummarizerPlayer::MetricsSummarizerPlayer(const char *key) setIgnorables(player_ignorable); } // NB: this is also called for the first time -- so summation == item // Not sure if we need a flag for that or not. // In this particular mergeRecord() code -- we're' ok for this. void MetricsSummarizerPlayer::mergeRecord(MediaAnalyticsItem &summation, MediaAnalyticsItem &item) { ALOGV("MetricsSummarizerPlayer::mergeRecord()"); // // we sum time & frames. // be careful about our special "-1" values that indicate 'unknown' // treat those as 0 [basically, not summing them into the totals]. int64_t duration = 0; if (item.getInt64("android.media.mediaplayer.durationMs", &duration)) { ALOGV("found durationMs of %" PRId64, duration); summation.addInt64("android.media.mediaplayer.durationMs",duration); minMaxVar64(summation, "android.media.mediaplayer.durationMs", duration); } int64_t playing = 0; if (item.getInt64("android.media.mediaplayer.playingMs", &playing)) if (item.getInt64("android.media.mediaplayer.playingMs", &playing)) { ALOGV("found playingMs of %" PRId64, playing); } if (playing >= 0) { summation.addInt64("android.media.mediaplayer.playingMs",playing); minMaxVar64(summation,"android.media.mediaplayer.playingMs",playing); } int64_t frames = 0; if (item.getInt64("android.media.mediaplayer.frames", &frames)) if (item.getInt64("android.media.mediaplayer.frames", &frames)) { ALOGV("found framess of %" PRId64, frames); } if (frames >= 0) { summation.addInt64("android.media.mediaplayer.frames",frames); minMaxVar64(summation,"android.media.mediaplayer.frames",frames); } int64_t dropped = 0; if (item.getInt64("android.media.mediaplayer.dropped", &dropped)) if (item.getInt64("android.media.mediaplayer.dropped", &dropped)) { ALOGV("found dropped of %" PRId64, dropped); } if (dropped >= 0) { summation.addInt64("android.media.mediaplayer.dropped",dropped); minMaxVar64(summation,"android.media.mediaplayer.dropped",dropped); } } Loading Loading
services/mediaanalytics/MetricsSummarizer.cpp +98 −32 Original line number Diff line number Diff line Loading @@ -141,23 +141,23 @@ void MetricsSummarizer::handleRecord(MediaAnalyticsItem *item) { List<MediaAnalyticsItem *>::iterator it = mSummaries->begin(); for (; it != mSummaries->end(); it++) { bool good = sameAttributes((*it), item, getIgnorables()); ALOGV("Match against %s says %d", (*it)->toString().c_str(), good); ALOGV("Match against %s says %d", (*it)->toString().c_str(), good); if (good) break; } if (it == mSummaries->end()) { ALOGV("save new record"); item = item->dup(); if (item == NULL) { MediaAnalyticsItem *nitem = item->dup(); if (nitem == NULL) { ALOGE("unable to save MediaMetrics record"); } sortProps(item); item->setInt32("count",1); mSummaries->push_back(item); sortProps(nitem); nitem->setInt32("aggregated",1); mergeRecord(*nitem, *item); mSummaries->push_back(nitem); } else { ALOGV("increment existing record"); (*it)->addInt32("count",1); (*it)->addInt32("aggregated",1); mergeRecord(*(*it), *item); } } Loading @@ -168,6 +168,71 @@ void MetricsSummarizer::mergeRecord(MediaAnalyticsItem &/*have*/, MediaAnalytics return; } // keep some stats for things: sums, counts, standard deviation // the integer version -- all of these pieces are in 64 bits void MetricsSummarizer::minMaxVar64(MediaAnalyticsItem &summation, const char *key, int64_t value) { if (key == NULL) return; int len = strlen(key) + 32; char *tmpKey = (char *)malloc(len); if (tmpKey == NULL) { return; } // N - count of samples snprintf(tmpKey, len, "%s.n", key); summation.addInt64(tmpKey, 1); // zero - count of samples that are zero if (value == 0) { snprintf(tmpKey, len, "%s.zero", key); int64_t zero = 0; (void) summation.getInt64(tmpKey,&zero); zero++; summation.setInt64(tmpKey, zero); } // min snprintf(tmpKey, len, "%s.min", key); int64_t min = value; if (summation.getInt64(tmpKey,&min)) { if (min > value) { summation.setInt64(tmpKey, value); } } else { summation.setInt64(tmpKey, value); } // max snprintf(tmpKey, len, "%s.max", key); int64_t max = value; if (summation.getInt64(tmpKey,&max)) { if (max < value) { summation.setInt64(tmpKey, value); } } else { summation.setInt64(tmpKey, value); } // components for mean, stddev; // stddev = sqrt(1/4*(sumx2 - (2*sumx*sumx/n) + ((sumx/n)^2))) // sum x snprintf(tmpKey, len, "%s.sumX", key); summation.addInt64(tmpKey, value); // sum x^2 snprintf(tmpKey, len, "%s.sumX2", key); summation.addInt64(tmpKey, value*value); // last thing we do -- remove the base key from the summation // record so we won't get confused about it having both individual // and summary information in there. summation.removeProp(key); free(tmpKey); } // // Comparators Loading @@ -186,20 +251,23 @@ bool MetricsSummarizer::sameAttributes(MediaAnalyticsItem *summ, MediaAnalyticsI ALOGV("MetricsSummarizer::sameAttributes(): summ %s", summ->toString().c_str()); ALOGV("MetricsSummarizer::sameAttributes(): single %s", single->toString().c_str()); // keep different sources/users separate if (single->mUid != summ->mUid) { return false; } // this can be made better. for(size_t i=0;i<single->mPropCount;i++) { MediaAnalyticsItem::Prop *prop1 = &(single->mProps[i]); const char *attrName = prop1->mName; ALOGV("compare on attr '%s'", attrName); // is it something we should ignore if (ignorable != NULL) { const char **ig = ignorable; while (*ig) { for (;*ig; ig++) { if (strcmp(*ig, attrName) == 0) { break; } ig++; } if (*ig) { ALOGV("we don't mind that it has attr '%s'", attrName); Loading @@ -218,29 +286,42 @@ bool MetricsSummarizer::sameAttributes(MediaAnalyticsItem *summ, MediaAnalyticsI } switch (prop1->mType) { case MediaAnalyticsItem::kTypeInt32: if (prop1->u.int32Value != prop2->u.int32Value) if (prop1->u.int32Value != prop2->u.int32Value) { ALOGV("mismatch values"); return false; } break; case MediaAnalyticsItem::kTypeInt64: if (prop1->u.int64Value != prop2->u.int64Value) if (prop1->u.int64Value != prop2->u.int64Value) { ALOGV("mismatch values"); return false; } break; case MediaAnalyticsItem::kTypeDouble: // XXX: watch out for floating point comparisons! if (prop1->u.doubleValue != prop2->u.doubleValue) if (prop1->u.doubleValue != prop2->u.doubleValue) { ALOGV("mismatch values"); return false; } break; case MediaAnalyticsItem::kTypeCString: if (strcmp(prop1->u.CStringValue, prop2->u.CStringValue) != 0) if (strcmp(prop1->u.CStringValue, prop2->u.CStringValue) != 0) { ALOGV("mismatch values"); return false; } break; case MediaAnalyticsItem::kTypeRate: if (prop1->u.rate.count != prop2->u.rate.count) if (prop1->u.rate.count != prop2->u.rate.count) { ALOGV("mismatch values"); return false; if (prop1->u.rate.duration != prop2->u.rate.duration) } if (prop1->u.rate.duration != prop2->u.rate.duration) { ALOGV("mismatch values"); return false; } break; default: ALOGV("mismatch values in default type"); return false; } } Loading @@ -248,15 +329,6 @@ bool MetricsSummarizer::sameAttributes(MediaAnalyticsItem *summ, MediaAnalyticsI return true; } bool MetricsSummarizer::sameAttributesId(MediaAnalyticsItem *summ, MediaAnalyticsItem *single, const char **ignorable) { // verify same user if (summ->mPid != single->mPid) return false; // and finally do the more expensive validation of the attributes return sameAttributes(summ, single, ignorable); } int MetricsSummarizer::PropSorter(const void *a, const void *b) { MediaAnalyticsItem::Prop *ai = (MediaAnalyticsItem::Prop *)a; Loading @@ -267,14 +339,8 @@ int MetricsSummarizer::PropSorter(const void *a, const void *b) { // we sort in the summaries so that it looks pretty in the dumpsys void MetricsSummarizer::sortProps(MediaAnalyticsItem *item) { if (item->mPropCount != 0) { if (DEBUG_SORT) { ALOGD("sortProps(pre): %s", item->toString().c_str()); } qsort(item->mProps, item->mPropCount, sizeof(MediaAnalyticsItem::Prop), MetricsSummarizer::PropSorter); if (DEBUG_SORT) { ALOGD("sortProps(pst): %s", item->toString().c_str()); } } } Loading
services/mediaanalytics/MetricsSummarizer.h +2 −3 Original line number Diff line number Diff line Loading @@ -59,10 +59,9 @@ class MetricsSummarizer // various comparators // "do these records have same attributes and values in those attrs" // ditto, but watch for "error" fields bool sameAttributes(MediaAnalyticsItem *summ, MediaAnalyticsItem *single, const char **ignoreables); // attributes + from the same app/userid bool sameAttributesId(MediaAnalyticsItem *summ, MediaAnalyticsItem *single, const char **ignoreables); void minMaxVar64(MediaAnalyticsItem &summ, const char *key, int64_t value); static int PropSorter(const void *a, const void *b); void sortProps(MediaAnalyticsItem *item); Loading
services/mediaanalytics/MetricsSummarizerPlayer.cpp +23 −17 Original line number Diff line number Diff line Loading @@ -51,36 +51,42 @@ MetricsSummarizerPlayer::MetricsSummarizerPlayer(const char *key) setIgnorables(player_ignorable); } // NB: this is also called for the first time -- so summation == item // Not sure if we need a flag for that or not. // In this particular mergeRecord() code -- we're' ok for this. void MetricsSummarizerPlayer::mergeRecord(MediaAnalyticsItem &summation, MediaAnalyticsItem &item) { ALOGV("MetricsSummarizerPlayer::mergeRecord()"); // // we sum time & frames. // be careful about our special "-1" values that indicate 'unknown' // treat those as 0 [basically, not summing them into the totals]. int64_t duration = 0; if (item.getInt64("android.media.mediaplayer.durationMs", &duration)) { ALOGV("found durationMs of %" PRId64, duration); summation.addInt64("android.media.mediaplayer.durationMs",duration); minMaxVar64(summation, "android.media.mediaplayer.durationMs", duration); } int64_t playing = 0; if (item.getInt64("android.media.mediaplayer.playingMs", &playing)) if (item.getInt64("android.media.mediaplayer.playingMs", &playing)) { ALOGV("found playingMs of %" PRId64, playing); } if (playing >= 0) { summation.addInt64("android.media.mediaplayer.playingMs",playing); minMaxVar64(summation,"android.media.mediaplayer.playingMs",playing); } int64_t frames = 0; if (item.getInt64("android.media.mediaplayer.frames", &frames)) if (item.getInt64("android.media.mediaplayer.frames", &frames)) { ALOGV("found framess of %" PRId64, frames); } if (frames >= 0) { summation.addInt64("android.media.mediaplayer.frames",frames); minMaxVar64(summation,"android.media.mediaplayer.frames",frames); } int64_t dropped = 0; if (item.getInt64("android.media.mediaplayer.dropped", &dropped)) if (item.getInt64("android.media.mediaplayer.dropped", &dropped)) { ALOGV("found dropped of %" PRId64, dropped); } if (dropped >= 0) { summation.addInt64("android.media.mediaplayer.dropped",dropped); minMaxVar64(summation,"android.media.mediaplayer.dropped",dropped); } } Loading