From ba8c48429d82d22737a84d2713fa1880a4654cbd Mon Sep 17 00:00:00 2001 From: Ray Essick Date: Fri, 18 Jan 2019 11:35:33 -0800 Subject: [PATCH 1/2] 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 --- media/libmediametrics/Android.bp | 21 +- .../IMediaAnalyticsService.cpp | 2 +- media/libmediametrics/MediaAnalyticsItem.cpp | 207 +++++++++++++++++- media/libmediametrics/MediaMetrics.cpp | 19 +- .../include/MediaAnalyticsItem.h | 15 +- media/libmediametrics/include/MediaMetrics.h | 10 +- media/libmediametrics/libmediametrics.map.txt | 29 +++ 7 files changed, 266 insertions(+), 37 deletions(-) create mode 100644 media/libmediametrics/libmediametrics.map.txt diff --git a/media/libmediametrics/Android.bp b/media/libmediametrics/Android.bp index e188e54fb3..15ea578fdb 100644 --- a/media/libmediametrics/Android.bp +++ b/media/libmediametrics/Android.bp @@ -1,6 +1,4 @@ -// TODO: change it back to cc_library_shared when there is a way to -// expose media metrics as stable API. -cc_library { +cc_library_shared { name: "libmediametrics", srcs: [ @@ -32,12 +30,13 @@ cc_library { cfi: true, }, - // enumerate the stable interface -// this would mean nobody can use the C++ interface. have to rework some things. -// stubs: { -// symbol_file: "libmediametrics.map.txt", -// versions: [ -// "1" , -// ] -// }, + // enumerate stable entry points, for apex use + stubs: { + symbol_file: "libmediametrics.map.txt", + versions: [ + "1" , + ] + }, } + + diff --git a/media/libmediametrics/IMediaAnalyticsService.cpp b/media/libmediametrics/IMediaAnalyticsService.cpp index 28a77462b2..9114927dac 100644 --- a/media/libmediametrics/IMediaAnalyticsService.cpp +++ b/media/libmediametrics/IMediaAnalyticsService.cpp @@ -142,7 +142,7 @@ status_t BnMediaAnalyticsService::onTransact( CHECK_INTERFACE(IMediaAnalyticsService, data, reply); bool forcenew; - MediaAnalyticsItem *item = new MediaAnalyticsItem; + MediaAnalyticsItem *item = MediaAnalyticsItem::create(); data.readBool(&forcenew); item->readFromParcel(data); diff --git a/media/libmediametrics/MediaAnalyticsItem.cpp b/media/libmediametrics/MediaAnalyticsItem.cpp index 448e2d9959..02c23b1231 100644 --- a/media/libmediametrics/MediaAnalyticsItem.cpp +++ b/media/libmediametrics/MediaAnalyticsItem.cpp @@ -52,6 +52,17 @@ const char * const MediaAnalyticsItem::EnabledProperty = "media.metrics.enabled 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 @@ bool MediaAnalyticsItem::growProps(int increment) // 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::readFromParcel(const Parcel& data) { } 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 @@ int32_t MediaAnalyticsItem::writeToParcel(Parcel *data) { return 0; } - const char *MediaAnalyticsItem::toCString() { return toCString(PROTO_LAST); } @@ -876,8 +914,6 @@ bool MediaAnalyticsItem::selfrecord(bool forcenew) { } 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 @@ bool MediaAnalyticsItem::merge(MediaAnalyticsItem *incoming) { 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 diff --git a/media/libmediametrics/MediaMetrics.cpp b/media/libmediametrics/MediaMetrics.cpp index 9b08aa74fd..61091900c0 100644 --- a/media/libmediametrics/MediaMetrics.cpp +++ b/media/libmediametrics/MediaMetrics.cpp @@ -34,7 +34,7 @@ // manage the overall record mediametrics_handle_t mediametrics_create(mediametricskey_t key) { - android::MediaAnalyticsItem *item = new android::MediaAnalyticsItem(key); + android::MediaAnalyticsItem *item = android::MediaAnalyticsItem::create(key); return (mediametrics_handle_t) item; } @@ -187,18 +187,9 @@ bool mediametrics_isEnabled() { return android::MediaAnalyticsItem::isEnabled(); } -#if 0 -// do not expose this as is. -// need to revisit (or redefine) how the android::Parcel parameter is handled -// so that it meets the stable-API criteria for updateable components. -// -int32_t mediametrics_writeToParcel(mediametrics_handle_t handle, android::Parcel *parcel) { +bool mediametrics_getAttributes(mediametrics_handle_t handle, char **buffer, size_t *length) { android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle; - if (item == NULL) { - return -1; - } - return item->writeToParcel(parcel); -} -#endif - + if (item == NULL) return false; + return item->dumpAttributes(buffer, length); +} diff --git a/media/libmediametrics/include/MediaAnalyticsItem.h b/media/libmediametrics/include/MediaAnalyticsItem.h index b99cd91c1c..2f9e7c204f 100644 --- a/media/libmediametrics/include/MediaAnalyticsItem.h +++ b/media/libmediametrics/include/MediaAnalyticsItem.h @@ -17,9 +17,10 @@ #ifndef ANDROID_MEDIA_MEDIAANALYTICSITEM_H #define ANDROID_MEDIA_MEDIAANALYTICSITEM_H -#include #include #include + +#include #include #include #include @@ -84,6 +85,10 @@ class MediaAnalyticsItem { public: + // so clients do not need to know size details + static MediaAnalyticsItem* create(Key key); + static MediaAnalyticsItem* create(); + // access functions for the class MediaAnalyticsItem(); MediaAnalyticsItem(Key); @@ -175,6 +180,9 @@ class MediaAnalyticsItem { int32_t writeToParcel(Parcel *); int32_t readFromParcel(const Parcel&); + // supports the stable interface + bool dumpAttributes(char **pbuffer, size_t *plength); + std::string toString(); std::string toString(int version); const char *toCString(); @@ -183,6 +191,11 @@ class MediaAnalyticsItem { // are we collecting analytics data static bool isEnabled(); + private: + // handle Parcel version 0 + int32_t writeToParcel0(Parcel *); + int32_t readFromParcel0(const Parcel&); + protected: // merge fields from arg into this diff --git a/media/libmediametrics/include/MediaMetrics.h b/media/libmediametrics/include/MediaMetrics.h index 4d2f352984..a4e1ed2c13 100644 --- a/media/libmediametrics/include/MediaMetrics.h +++ b/media/libmediametrics/include/MediaMetrics.h @@ -85,13 +85,9 @@ const char *mediametrics_readable(mediametrics_handle_t handle); void mediametrics_setUid(mediametrics_handle_t handle, uid_t uid); bool mediametrics_isEnabled(); -#if 0 -// do not expose this as is. -// need to revisit (or redefine) how the android::Parcel parameter is handled -// so that it meets the stable-API criteria for updateable components. -// -int32_t mediametrics_writeToParcel(mediametrics_handle_t handle, android::Parcel *parcel); -#endif +// serialized copy of the attributes/values, mostly for upstream getMetrics() calls +// caller owns the buffer allocated as part of this call. +bool mediametrics_getAttributes(mediametrics_handle_t handle, char **buffer, size_t *length); __END_DECLS diff --git a/media/libmediametrics/libmediametrics.map.txt b/media/libmediametrics/libmediametrics.map.txt new file mode 100644 index 0000000000..c46281aa63 --- /dev/null +++ b/media/libmediametrics/libmediametrics.map.txt @@ -0,0 +1,29 @@ +LIBMEDIAMETRICS_1 { + global: + mediametrics_addDouble; # apex + mediametrics_addInt32; # apex + mediametrics_addInt64; # apex + mediametrics_addRate; # apex + mediametrics_count; # apex + mediametrics_create; # apex + mediametrics_delete; # apex + mediametrics_freeCString; # apex + mediametrics_getAttributes; # apex + mediametrics_getCString; # apex + mediametrics_getDouble; # apex + mediametrics_getInt32; # apex + mediametrics_getInt64; # apex + mediametrics_getKey; # apex + mediametrics_getRate; # apex + mediametrics_isEnabled; # apex + mediametrics_readable; # apex + mediametrics_selfRecord; # apex + mediametrics_setCString; # apex + mediametrics_setDouble; # apex + mediametrics_setInt32; # apex + mediametrics_setInt64; # apex + mediametrics_setRate; # apex + mediametrics_setUid; # apex + local: + *; +}; From 89269d69b4d93deed90aa50881d0a5d88b3fd8d9 Mon Sep 17 00:00:00 2001 From: Ray Essick Date: Sun, 20 Jan 2019 14:46:19 -0800 Subject: [PATCH 2/2] MediaPlayer2 using the new mediametrics stable interface converts mediaplayer2 to use the new interface. Bug: 112555455 Test: boot / relevant ctsMediaTests Change-Id: I186c1931408414e9fd42bbc501e636a9624b6a6e --- .../mediaplayer2/MediaPlayer2Interface.h | 2 + .../include/mediaplayer2/mediaplayer2.h | 1 + media/libmediaplayer2/mediaplayer2.cpp | 17 +++- media/libmediaplayer2/nuplayer2/Android.bp | 1 + .../nuplayer2/NuPlayer2Decoder.cpp | 2 + .../nuplayer2/NuPlayer2Driver.cpp | 85 +++++++++---------- .../nuplayer2/NuPlayer2Driver.h | 5 +- 7 files changed, 66 insertions(+), 47 deletions(-) diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h index 0c8d016902..7804a62df0 100644 --- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h +++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h @@ -214,6 +214,8 @@ public: virtual status_t setParameter(int key, const Parcel &request) = 0; virtual status_t getParameter(int key, Parcel *reply) = 0; + virtual status_t getMetrics(char **buffer, size_t *length) = 0; + // Invoke a generic method on the player by using opaque parcels // for the request and reply. // diff --git a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h index 78865c448d..2993ab1063 100644 --- a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h +++ b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h @@ -102,6 +102,7 @@ public: status_t setAudioAttributes(const jobject attributes); jobject getAudioAttributes(); status_t getParameter(int key, Parcel* reply); + status_t getMetrics(char **buffer, size_t *length); // Modular DRM status_t prepareDrm(int64_t srcId, diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp index f75380ced6..53f2fb12c8 100644 --- a/media/libmediaplayer2/mediaplayer2.cpp +++ b/media/libmediaplayer2/mediaplayer2.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -979,6 +978,22 @@ status_t MediaPlayer2::getParameter(int key, Parcel *reply) { return status; } +// for mediametrics +status_t MediaPlayer2::getMetrics(char **buffer, size_t *length) { + ALOGD("MediaPlayer2::getMetrics()"); + Mutex::Autolock _l(mLock); + if (mPlayer == NULL) { + ALOGV("getMetrics: no active player"); + return INVALID_OPERATION; + } + + status_t status = mPlayer->getMetrics(buffer, length); + if (status != OK) { + ALOGD("getMetrics returns %d", status); + } + return status; +} + void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *obj) { ALOGV("message received srcId=%lld, msg=%d, ext1=%d, ext2=%d", (long long)srcId, msg, ext1, ext2); diff --git a/media/libmediaplayer2/nuplayer2/Android.bp b/media/libmediaplayer2/nuplayer2/Android.bp index 71cd50f628..0f69b2eabe 100644 --- a/media/libmediaplayer2/nuplayer2/Android.bp +++ b/media/libmediaplayer2/nuplayer2/Android.bp @@ -51,6 +51,7 @@ cc_library_static { "libui", "libgui", "libmedia", + "libmediametrics", "libmediandk", "libmediandk_utils", "libpowermanager", diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp index a5bd62d0fd..9729d86964 100644 --- a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp +++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp @@ -107,6 +107,8 @@ sp NuPlayer2::Decoder::getStats() const { mStats->setInt64("frames-total", mNumFramesTotal); mStats->setInt64("frames-dropped-input", mNumInputFramesDropped); mStats->setInt64("frames-dropped-output", mNumOutputFramesDropped); + mStats->setFloat("frame-rate-total", mFrameRateTotal); + return mStats; } diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp index 56e9471f2a..1b661f291e 100644 --- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp +++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp @@ -92,6 +92,7 @@ static const char *kPlayerWidth = "android.media.mediaplayer.width"; static const char *kPlayerHeight = "android.media.mediaplayer.height"; static const char *kPlayerFrames = "android.media.mediaplayer.frames"; static const char *kPlayerFramesDropped = "android.media.mediaplayer.dropped"; +static const char *kPlayerFrameRate = "android.media.mediaplayer.fps"; static const char *kPlayerAMime = "android.media.mediaplayer.audio.mime"; static const char *kPlayerACodec = "android.media.mediaplayer.audio.codec"; static const char *kPlayerDuration = "android.media.mediaplayer.durationMs"; @@ -125,7 +126,7 @@ NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid, const sp & mMediaClock(new MediaClock), mPlayer(new NuPlayer2(pid, uid, mMediaClock, context)), mPlayerFlags(0), - mAnalyticsItem(NULL), + mMetricsHandle(0), mClientUid(uid), mAtEOS(false), mLooping(false), @@ -136,9 +137,9 @@ NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid, const sp & mMediaClock->init(); - // set up an analytics record - mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer); - mAnalyticsItem->setUid(mClientUid); + // set up media metrics record + mMetricsHandle = mediametrics_create(kKeyPlayer); + mediametrics_setUid(mMetricsHandle, mClientUid); mNuPlayer2Looper->start( false, /* runOnCallingThread */ @@ -159,10 +160,7 @@ NuPlayer2Driver::~NuPlayer2Driver() { updateMetrics("destructor"); logMetrics("destructor"); - if (mAnalyticsItem != NULL) { - delete mAnalyticsItem; - mAnalyticsItem = NULL; - } + mediametrics_delete(mMetricsHandle); } status_t NuPlayer2Driver::initCheck() { @@ -453,15 +451,15 @@ void NuPlayer2Driver::updateMetrics(const char *where) { if (mime.startsWith("video/")) { int32_t width, height; - mAnalyticsItem->setCString(kPlayerVMime, mime.c_str()); + mediametrics_setCString(mMetricsHandle, kPlayerVMime, mime.c_str()); if (!name.empty()) { - mAnalyticsItem->setCString(kPlayerVCodec, name.c_str()); + mediametrics_setCString(mMetricsHandle, kPlayerVCodec, name.c_str()); } if (stats->findInt32("width", &width) && stats->findInt32("height", &height)) { - mAnalyticsItem->setInt32(kPlayerWidth, width); - mAnalyticsItem->setInt32(kPlayerHeight, height); + mediametrics_setInt32(mMetricsHandle, kPlayerWidth, width); + mediametrics_setInt32(mMetricsHandle, kPlayerHeight, height); } int64_t numFramesTotal = 0; @@ -469,14 +467,18 @@ void NuPlayer2Driver::updateMetrics(const char *where) { stats->findInt64("frames-total", &numFramesTotal); stats->findInt64("frames-dropped-output", &numFramesDropped); - mAnalyticsItem->setInt64(kPlayerFrames, numFramesTotal); - mAnalyticsItem->setInt64(kPlayerFramesDropped, numFramesDropped); + mediametrics_setInt64(mMetricsHandle, kPlayerFrames, numFramesTotal); + mediametrics_setInt64(mMetricsHandle, kPlayerFramesDropped, numFramesDropped); + float frameRate = 0; + if (stats->findFloat("frame-rate-output", &frameRate)) { + mediametrics_setInt64(mMetricsHandle, kPlayerFrameRate, frameRate); + } } else if (mime.startsWith("audio/")) { - mAnalyticsItem->setCString(kPlayerAMime, mime.c_str()); + mediametrics_setCString(mMetricsHandle, kPlayerAMime, mime.c_str()); if (!name.empty()) { - mAnalyticsItem->setCString(kPlayerACodec, name.c_str()); + mediametrics_setCString(mMetricsHandle, kPlayerACodec, name.c_str()); } } } @@ -487,17 +489,17 @@ void NuPlayer2Driver::updateMetrics(const char *where) { // getDuration() uses mLock for mutex -- careful where we use it. int64_t duration_ms = -1; getDuration(&duration_ms); - mAnalyticsItem->setInt64(kPlayerDuration, duration_ms); + mediametrics_setInt64(mMetricsHandle, kPlayerDuration, duration_ms); - mAnalyticsItem->setInt64(kPlayerPlaying, (mPlayingTimeUs+500)/1000 ); + mediametrics_setInt64(mMetricsHandle, kPlayerPlaying, (mPlayingTimeUs+500)/1000 ); if (mRebufferingEvents != 0) { - mAnalyticsItem->setInt64(kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 ); - mAnalyticsItem->setInt32(kPlayerRebufferingCount, mRebufferingEvents); - mAnalyticsItem->setInt32(kPlayerRebufferingAtExit, mRebufferingAtExit); + mediametrics_setInt64(mMetricsHandle, kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 ); + mediametrics_setInt32(mMetricsHandle, kPlayerRebufferingCount, mRebufferingEvents); + mediametrics_setInt32(mMetricsHandle, kPlayerRebufferingAtExit, mRebufferingAtExit); } - mAnalyticsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType()); + mediametrics_setCString(mMetricsHandle, kPlayerDataSourceType, mPlayer->getDataSourceType()); } @@ -507,7 +509,7 @@ void NuPlayer2Driver::logMetrics(const char *where) { } ALOGV("logMetrics(%p) from %s at state %d", this, where, mState); - if (mAnalyticsItem == NULL || mAnalyticsItem->isEnabled() == false) { + if (mMetricsHandle == 0 || mediametrics_isEnabled() == false) { return; } @@ -516,16 +518,12 @@ void NuPlayer2Driver::logMetrics(const char *where) { // and that always injects 3 fields (duration, playing time, and // datasource) into the record. // So the canonical "empty" record has 3 elements in it. - if (mAnalyticsItem->count() > 3) { - - mAnalyticsItem->selfrecord(); - + if (mediametrics_count(mMetricsHandle) > 3) { + mediametrics_selfRecord(mMetricsHandle); // re-init in case we prepare() and start() again. - delete mAnalyticsItem ; - mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer); - if (mAnalyticsItem) { - mAnalyticsItem->setUid(mClientUid); - } + mediametrics_delete(mMetricsHandle); + mMetricsHandle = mediametrics_create(kKeyPlayer); + mediametrics_setUid(mMetricsHandle, mClientUid); } else { ALOGV("did not have anything to record"); } @@ -649,17 +647,16 @@ status_t NuPlayer2Driver::setParameter( return INVALID_OPERATION; } -status_t NuPlayer2Driver::getParameter(int key, Parcel *reply) { +status_t NuPlayer2Driver::getParameter(int key __unused, Parcel *reply __unused) { + return INVALID_OPERATION; +} - if (key == FOURCC('m','t','r','X')) { - // mtrX -- a play on 'metrics' (not matrix) - // gather current info all together, parcel it, and send it back - updateMetrics("api"); - mAnalyticsItem->writeToParcel(reply); +status_t NuPlayer2Driver::getMetrics(char **buffer, size_t *length) { + updateMetrics("api"); + if (mediametrics_getAttributes(mMetricsHandle, buffer, length)) return OK; - } - - return INVALID_OPERATION; + else + return FAILED_TRANSACTION; } void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) { @@ -867,11 +864,11 @@ void NuPlayer2Driver::notifyListener_l( // ext1 is our primary 'error type' value. Only add ext2 when non-zero. // [test against msg is due to fall through from previous switch value] if (msg == MEDIA2_ERROR) { - mAnalyticsItem->setInt32(kPlayerError, ext1); + mediametrics_setInt32(mMetricsHandle, kPlayerError, ext1); if (ext2 != 0) { - mAnalyticsItem->setInt32(kPlayerErrorCode, ext2); + mediametrics_setInt32(mMetricsHandle, kPlayerErrorCode, ext2); } - mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str()); + mediametrics_setCString(mMetricsHandle, kPlayerErrorState, stateString(mState).c_str()); } mAtEOS = true; break; diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h index 0ec3a4b23b..3d299f3582 100644 --- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h +++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h @@ -16,7 +16,7 @@ #include -#include +#include #include #include @@ -61,6 +61,7 @@ struct NuPlayer2Driver : public MediaPlayer2Interface { virtual void setAudioSink(const sp &audioSink) override; virtual status_t setParameter(int key, const Parcel &request) override; virtual status_t getParameter(int key, Parcel *reply) override; + virtual status_t getMetrics(char **buf, size_t *length) override; virtual status_t dump(int fd, const Vector &args) const override; @@ -132,7 +133,7 @@ private: sp mAudioSink; uint32_t mPlayerFlags; - MediaAnalyticsItem *mAnalyticsItem; + mediametrics_handle_t mMetricsHandle; uid_t mClientUid; bool mAtEOS;