track pkgname/version in media.metrics
Enhances the media.metrics subsystem to track the pkg name & version
so analysis can move from "error rate has climbed" to "error rate has
climbed within app X".
Changes include fields to hold package name/version, the dump protocol
to emit those fields to upload, and better management of metrics data on
device (time and quantity).
Bug: 65027506
Test: review output of dumpsys media.metrics
Change-Id: Ia55b859d903835c84f7d43883f959dc1cdefb081
diff --git a/media/libmediametrics/MediaAnalyticsItem.cpp b/media/libmediametrics/MediaAnalyticsItem.cpp
index 43881b3..47a147e 100644
--- a/media/libmediametrics/MediaAnalyticsItem.cpp
+++ b/media/libmediametrics/MediaAnalyticsItem.cpp
@@ -120,6 +120,8 @@
// key as part of constructor
dst->mPid = this->mPid;
dst->mUid = this->mUid;
+ dst->mPkgName = this->mPkgName;
+ dst->mPkgVersionCode = this->mPkgVersionCode;
dst->mSessionID = this->mSessionID;
dst->mTimestamp = this->mTimestamp;
dst->mFinalized = this->mFinalized;
@@ -201,6 +203,24 @@
return mUid;
}
+MediaAnalyticsItem &MediaAnalyticsItem::setPkgName(AString pkgName) {
+ mPkgName = pkgName;
+ return *this;
+}
+
+AString MediaAnalyticsItem::getPkgName() const {
+ return mPkgName;
+}
+
+MediaAnalyticsItem &MediaAnalyticsItem::setPkgVersionCode(int32_t pkgVersionCode) {
+ mPkgVersionCode = pkgVersionCode;
+ return *this;
+}
+
+int32_t MediaAnalyticsItem::getPkgVersionCode() const {
+ return mPkgVersionCode;
+}
+
// this key is for the overall record -- "codec", "player", "drm", etc
MediaAnalyticsItem &MediaAnalyticsItem::setKey(MediaAnalyticsItem::Key key) {
mKey = key;
@@ -263,11 +283,29 @@
i = mPropCount++;
prop = &mProps[i];
prop->setName(name, len);
+ prop->mType = kTypeNone; // make caller set type info
}
return prop;
}
+// used within the summarizers; return whether property existed
+bool MediaAnalyticsItem::removeProp(const char *name) {
+ size_t len = strlen(name);
+ size_t i = findPropIndex(name, len);
+ if (i < mPropCount) {
+ Prop *prop = &mProps[i];
+ clearProp(prop);
+ if (i != mPropCount-1) {
+ // in the middle, bring last one down to fill gap
+ mProps[i] = mProps[mPropCount-1];
+ }
+ mPropCount--;
+ return true;
+ }
+ return false;
+}
+
// set the values
void MediaAnalyticsItem::setInt32(MediaAnalyticsItem::Attr name, int32_t value) {
Prop *prop = allocateProp(name);
@@ -568,6 +606,10 @@
// into 'this' object
// .. we make a copy of the string to put away.
mKey = data.readCString();
+ mPid = data.readInt32();
+ mUid = data.readInt32();
+ mPkgName = data.readCString();
+ mPkgVersionCode = data.readInt32();
mSessionID = data.readInt64();
mFinalized = data.readInt32();
mTimestamp = data.readInt64();
@@ -611,6 +653,10 @@
data->writeCString(mKey.c_str());
+ data->writeInt32(mPid);
+ data->writeInt32(mUid);
+ data->writeCString(mPkgName.c_str());
+ data->writeInt32(mPkgVersionCode);
data->writeInt64(mSessionID);
data->writeInt32(mFinalized);
data->writeInt64(mTimestamp);
@@ -651,21 +697,54 @@
AString MediaAnalyticsItem::toString() {
+ return toString(-1);
+}
- AString result = "(";
+AString MediaAnalyticsItem::toString(int version) {
+
+ // v0 : released with 'o'
+ // v1 : bug fix (missing pid/finalized separator),
+ // adds apk name, apk version code
+
+ if (version <= PROTO_FIRST) {
+ // default to original v0 format, until proper parsers are in place
+ version = PROTO_V0;
+ } else if (version > PROTO_LAST) {
+ version = PROTO_LAST;
+ }
+
+ AString result;
char buffer[512];
+ if (version == PROTO_V0) {
+ result = "(";
+ } else {
+ snprintf(buffer, sizeof(buffer), "[%d:", version);
+ result.append(buffer);
+ }
+
// same order as we spill into the parcel, although not required
// key+session are our primary matching criteria
- //RBE ALOGD("mKey.c_str");
result.append(mKey.c_str());
- //RBE ALOGD("post-mKey.c_str");
result.append(":");
snprintf(buffer, sizeof(buffer), "%" PRId64 ":", mSessionID);
result.append(buffer);
- // we need these internally, but don't want to upload them
- snprintf(buffer, sizeof(buffer), "%d:%d", mUid, mPid);
+ snprintf(buffer, sizeof(buffer), "%d:", mUid);
+ result.append(buffer);
+
+ if (version >= PROTO_V1) {
+ result.append(mPkgName);
+ snprintf(buffer, sizeof(buffer), ":%d:", mPkgVersionCode);
+ result.append(buffer);
+ }
+
+ // in 'o' (v1) , the separator between pid and finalized was omitted
+ if (version <= PROTO_V0) {
+ snprintf(buffer, sizeof(buffer), "%d", mPid);
+ } else {
+ snprintf(buffer, sizeof(buffer), "%d:", mPid);
+ }
result.append(buffer);
snprintf(buffer, sizeof(buffer), "%d:", mFinalized);
@@ -713,7 +792,11 @@
result.append(buffer);
}
- result.append(")");
+ if (version == PROTO_V0) {
+ result.append(")");
+ } else {
+ result.append("]");
+ }
return result;
}
diff --git a/media/libmediametrics/include/MediaAnalyticsItem.h b/media/libmediametrics/include/MediaAnalyticsItem.h
index dc501b2..41b9658 100644
--- a/media/libmediametrics/include/MediaAnalyticsItem.h
+++ b/media/libmediametrics/include/MediaAnalyticsItem.h
@@ -75,6 +75,14 @@
typedef const char *Attr;
+ enum {
+ PROTO_V0 = 0,
+ PROTO_FIRST = PROTO_V0,
+ PROTO_V1 = 1,
+ PROTO_LAST = PROTO_V1,
+ };
+
+
public:
// access functions for the class
@@ -161,11 +169,18 @@
MediaAnalyticsItem &setUid(uid_t);
uid_t getUid() const;
+ MediaAnalyticsItem &setPkgName(AString);
+ AString getPkgName() const;
+
+ MediaAnalyticsItem &setPkgVersionCode(int32_t);
+ int32_t getPkgVersionCode() const;
+
// our serialization code for binder calls
int32_t writeToParcel(Parcel *);
int32_t readFromParcel(const Parcel&);
AString toString();
+ AString toString(int version);
// are we collecting analytics data
static bool isEnabled();
@@ -188,6 +203,8 @@
// to help validate that A doesn't mess with B's records
pid_t mPid;
uid_t mUid;
+ AString mPkgName;
+ int32_t mPkgVersionCode;
// let's reuse a binder connection
static sp<IMediaAnalyticsService> sAnalyticsService;
@@ -228,6 +245,7 @@
size_t findPropIndex(const char *name, size_t len);
Prop *findProp(const char *name);
Prop *allocateProp(const char *name);
+ bool removeProp(const char *name);
size_t mPropCount;
size_t mPropSize;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 0fc1aa7..dc29761 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -69,6 +69,7 @@
mPlayer(new NuPlayer(pid)),
mPlayerFlags(0),
mAnalyticsItem(NULL),
+ mClientUid(-1),
mAtEOS(false),
mLooping(false),
mAutoLoop(false) {
@@ -109,6 +110,10 @@
status_t NuPlayerDriver::setUID(uid_t uid) {
mPlayer->setUID(uid);
+ mClientUid = uid;
+ if (mAnalyticsItem) {
+ mAnalyticsItem->setUid(mClientUid);
+ }
return OK;
}
@@ -601,6 +606,7 @@
mAnalyticsItem = new MediaAnalyticsItem("nuplayer");
if (mAnalyticsItem) {
mAnalyticsItem->generateSessionID();
+ mAnalyticsItem->setUid(mClientUid);
}
} else {
ALOGV("did not have anything to record");
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index c5ddcb0..d0cf1dd 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -132,11 +132,13 @@
uint32_t mPlayerFlags;
MediaAnalyticsItem *mAnalyticsItem;
+ uid_t mClientUid;
bool mAtEOS;
bool mLooping;
bool mAutoLoop;
+
void updateMetrics(const char *where);
void logMetrics(const char *where);
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 5ef0f56..6f59fac 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -5224,6 +5224,7 @@
void MPEG4Extractor::populateMetrics() {
ALOGV("MPEG4Extractor::populateMetrics");
+ // write into mAnalyticsItem
}
static bool LegacySniffMPEG4(