Further work on libmediametrics stable API
implement a missing method (for inflight metrics), enumerate exported
symbols.
Bug: 119675363
Test: build, CTS media/codec tests
Change-Id: Id92f1b331babacc0de6c0005d6ba0c97c91c0291
diff --git a/media/libmediametrics/MediaAnalyticsItem.cpp b/media/libmediametrics/MediaAnalyticsItem.cpp
index 448e2d9..02c23b1 100644
--- a/media/libmediametrics/MediaAnalyticsItem.cpp
+++ b/media/libmediametrics/MediaAnalyticsItem.cpp
@@ -52,6 +52,17 @@
const char * const MediaAnalyticsItem::EnabledPropertyPersist = "persist.media.metrics.enabled";
const int MediaAnalyticsItem::EnabledProperty_default = 1;
+// So caller doesn't need to know size of allocated space
+MediaAnalyticsItem *MediaAnalyticsItem::create()
+{
+ return MediaAnalyticsItem::create(kKeyNone);
+}
+
+MediaAnalyticsItem *MediaAnalyticsItem::create(MediaAnalyticsItem::Key key)
+{
+ MediaAnalyticsItem *item = new MediaAnalyticsItem(key);
+ return item;
+}
// access functions for the class
MediaAnalyticsItem::MediaAnalyticsItem()
@@ -642,6 +653,19 @@
//
int32_t MediaAnalyticsItem::readFromParcel(const Parcel& data) {
+ int32_t version = data.readInt32();
+
+ switch(version) {
+ case 0:
+ return readFromParcel0(data);
+ break;
+ default:
+ ALOGE("Unsupported MediaAnalyticsItem Parcel version: %d", version);
+ return -1;
+ }
+}
+
+int32_t MediaAnalyticsItem::readFromParcel0(const Parcel& data) {
// into 'this' object
// .. we make a copy of the string to put away.
mKey = data.readCString();
@@ -691,8 +715,23 @@
}
int32_t MediaAnalyticsItem::writeToParcel(Parcel *data) {
+
if (data == NULL) return -1;
+ int32_t version = 0;
+ data->writeInt32(version);
+
+ switch(version) {
+ case 0:
+ return writeToParcel0(data);
+ break;
+ default:
+ ALOGE("Unsupported MediaAnalyticsItem Parcel version: %d", version);
+ return -1;
+ }
+}
+
+int32_t MediaAnalyticsItem::writeToParcel0(Parcel *data) {
data->writeCString(mKey.c_str());
data->writeInt32(mPid);
@@ -737,7 +776,6 @@
return 0;
}
-
const char *MediaAnalyticsItem::toCString() {
return toCString(PROTO_LAST);
}
@@ -876,8 +914,6 @@
}
return true;
} else {
- std::string p = this->toString();
- ALOGW("Unable to record: %s [forcenew=%d]", p.c_str(), forcenew);
return false;
}
}
@@ -1035,5 +1071,170 @@
return true;
}
+// a byte array; contents are
+// overall length (uint32) including the length field itself
+// encoding version (uint32)
+// count of properties (uint32)
+// N copies of:
+// property name as length(int16), bytes
+// the bytes WILL include the null terminator of the name
+// type (uint8 -- 1 byte)
+// size of value field (int16 -- 2 bytes)
+// value (size based on type)
+// int32, int64, double -- little endian 4/8/8 bytes respectively
+// cstring -- N bytes of value [WITH terminator]
+
+enum { kInt32 = 0, kInt64, kDouble, kRate, kCString};
+
+bool MediaAnalyticsItem::dumpAttributes(char **pbuffer, size_t *plength) {
+
+ char *build = NULL;
+
+ if (pbuffer == NULL || plength == NULL)
+ return false;
+
+ // consistency for the caller, who owns whatever comes back in this pointer.
+ *pbuffer = NULL;
+
+ // first, let's calculate sizes
+ int32_t goal = 0;
+ int32_t version = 0;
+
+ goal += sizeof(uint32_t); // overall length, including the length field
+ goal += sizeof(uint32_t); // encoding version
+ goal += sizeof(uint32_t); // # properties
+
+ int32_t count = mPropCount;
+ for (int i = 0 ; i < count; i++ ) {
+ Prop *prop = &mProps[i];
+ goal += sizeof(uint16_t); // name length
+ goal += strlen(prop->mName) + 1; // string + null
+ goal += sizeof(uint8_t); // type
+ goal += sizeof(uint16_t); // size of value
+ switch (prop->mType) {
+ case MediaAnalyticsItem::kTypeInt32:
+ goal += sizeof(uint32_t);
+ break;
+ case MediaAnalyticsItem::kTypeInt64:
+ goal += sizeof(uint64_t);
+ break;
+ case MediaAnalyticsItem::kTypeDouble:
+ goal += sizeof(double);
+ break;
+ case MediaAnalyticsItem::kTypeRate:
+ goal += 2 * sizeof(uint64_t);
+ break;
+ case MediaAnalyticsItem::kTypeCString:
+ // length + actual string + null
+ goal += strlen(prop->u.CStringValue) + 1;
+ break;
+ default:
+ ALOGE("found bad Prop type: %d, idx %d, name %s",
+ prop->mType, i, prop->mName);
+ return false;
+ }
+ }
+
+ // now that we have a size... let's allocate and fill
+ build = (char *)malloc(goal);
+ if (build == NULL)
+ return false;
+
+ memset(build, 0, goal);
+
+ char *filling = build;
+
+#define _INSERT(val, size) \
+ { memcpy(filling, &(val), (size)); filling += (size);}
+#define _INSERTSTRING(val, size) \
+ { memcpy(filling, (val), (size)); filling += (size);}
+
+ _INSERT(goal, sizeof(int32_t));
+ _INSERT(version, sizeof(int32_t));
+ _INSERT(count, sizeof(int32_t));
+
+ for (int i = 0 ; i < count; i++ ) {
+ Prop *prop = &mProps[i];
+ int16_t attrNameLen = strlen(prop->mName) + 1;
+ _INSERT(attrNameLen, sizeof(int16_t));
+ _INSERTSTRING(prop->mName, attrNameLen); // termination included
+ int8_t elemtype;
+ int16_t elemsize;
+ switch (prop->mType) {
+ case MediaAnalyticsItem::kTypeInt32:
+ {
+ elemtype = kInt32;
+ _INSERT(elemtype, sizeof(int8_t));
+ elemsize = sizeof(int32_t);
+ _INSERT(elemsize, sizeof(int16_t));
+
+ _INSERT(prop->u.int32Value, sizeof(int32_t));
+ break;
+ }
+ case MediaAnalyticsItem::kTypeInt64:
+ {
+ elemtype = kInt64;
+ _INSERT(elemtype, sizeof(int8_t));
+ elemsize = sizeof(int64_t);
+ _INSERT(elemsize, sizeof(int16_t));
+
+ _INSERT(prop->u.int64Value, sizeof(int64_t));
+ break;
+ }
+ case MediaAnalyticsItem::kTypeDouble:
+ {
+ elemtype = kDouble;
+ _INSERT(elemtype, sizeof(int8_t));
+ elemsize = sizeof(double);
+ _INSERT(elemsize, sizeof(int16_t));
+
+ _INSERT(prop->u.doubleValue, sizeof(double));
+ break;
+ }
+ case MediaAnalyticsItem::kTypeRate:
+ {
+ elemtype = kRate;
+ _INSERT(elemtype, sizeof(int8_t));
+ elemsize = 2 * sizeof(uint64_t);
+ _INSERT(elemsize, sizeof(int16_t));
+
+ _INSERT(prop->u.rate.count, sizeof(uint64_t));
+ _INSERT(prop->u.rate.duration, sizeof(uint64_t));
+ break;
+ }
+ case MediaAnalyticsItem::kTypeCString:
+ {
+ elemtype = kCString;
+ _INSERT(elemtype, sizeof(int8_t));
+ elemsize = strlen(prop->u.CStringValue) + 1;
+ _INSERT(elemsize, sizeof(int16_t));
+
+ _INSERTSTRING(prop->u.CStringValue, elemsize);
+ break;
+ }
+ default:
+ // error if can't encode; warning if can't decode
+ ALOGE("found bad Prop type: %d, idx %d, name %s",
+ prop->mType, i, prop->mName);
+ goto badness;
+ }
+ }
+
+ if (build + goal != filling) {
+ ALOGE("problems populating; wrote=%d planned=%d",
+ (int)(filling-build), goal);
+ goto badness;
+ }
+
+ *pbuffer = build;
+ *plength = goal;
+
+ return true;
+
+ badness:
+ free(build);
+ return false;
+}
+
} // namespace android