Move MediaMetrics into its own library
Changes for the new HAL structure have brought about a build time
circular dependency between libmedia and libmediadrm. This set of
changes the media metrics code into its own library and arranges
for the relevant consumers of the media metrics code to link
to this new library (where they had previously picked it up by
including libmedia).
Bug: 36990807
Test: build, boot.
Change-Id: I81768eecca88d5e59e6e6e547f29308a94e30c7b
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 8a1ce22..b0bd22e 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -26,7 +26,6 @@
IMediaPlayer.cpp \
IMediaRecorder.cpp \
IMediaSource.cpp \
- IMediaAnalyticsService.cpp \
IRemoteDisplay.cpp \
IRemoteDisplayClient.cpp \
IResourceManagerClient.cpp \
@@ -35,7 +34,6 @@
MediaCodecBuffer.cpp \
MediaCodecInfo.cpp \
MediaDefs.cpp \
- MediaAnalyticsItem.cpp \
MediaUtils.cpp \
Metadata.cpp \
mediarecorder.cpp \
@@ -66,6 +64,7 @@
libcamera_client libstagefright_foundation \
libgui libdl libaudioutils libaudioclient \
libmedia_helper libmediadrm \
+ libmediametrics \
libbase \
libhidlbase \
libhidltransport \
diff --git a/media/libmedia/IMediaAnalyticsService.cpp b/media/libmedia/IMediaAnalyticsService.cpp
deleted file mode 100644
index 340cf19..0000000
--- a/media/libmedia/IMediaAnalyticsService.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "MediaAnalytics"
-
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <binder/IPCThreadState.h>
-#include <media/IHDCP.h>
-#include <media/IMediaCodecList.h>
-#include <media/IMediaHTTPService.h>
-#include <media/IMediaPlayerService.h>
-#include <media/IMediaRecorder.h>
-#include <media/IOMX.h>
-#include <media/IRemoteDisplay.h>
-#include <media/IRemoteDisplayClient.h>
-#include <media/IStreamSource.h>
-
-#include <utils/Errors.h> // for status_t
-#include <utils/List.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include <media/MediaAnalyticsItem.h>
-#include <media/IMediaAnalyticsService.h>
-
-#define DEBUGGING 0
-#define DEBUGGING_FLOW 0
-#define DEBUGGING_RETURNS 0
-
-namespace android {
-
-enum {
- GENERATE_UNIQUE_SESSIONID = IBinder::FIRST_CALL_TRANSACTION,
- SUBMIT_ITEM,
-};
-
-class BpMediaAnalyticsService: public BpInterface<IMediaAnalyticsService>
-{
-public:
- explicit BpMediaAnalyticsService(const sp<IBinder>& impl)
- : BpInterface<IMediaAnalyticsService>(impl)
- {
- }
-
- virtual MediaAnalyticsItem::SessionID_t generateUniqueSessionID() {
- Parcel data, reply;
- status_t err;
- MediaAnalyticsItem::SessionID_t sessionid =
- MediaAnalyticsItem::SessionIDInvalid;
-
- data.writeInterfaceToken(IMediaAnalyticsService::getInterfaceDescriptor());
- err = remote()->transact(GENERATE_UNIQUE_SESSIONID, data, &reply);
- if (err != NO_ERROR) {
- ALOGW("bad response from service");
- return MediaAnalyticsItem::SessionIDInvalid;
- }
- sessionid = reply.readInt64();
- if (DEBUGGING_RETURNS) {
- ALOGD("the caller gets a sessionid of %" PRId64 " back", sessionid);
- }
- return sessionid;
- }
-
- virtual MediaAnalyticsItem::SessionID_t submit(MediaAnalyticsItem *item, bool forcenew)
- {
- // have this record submit itself
- // this will be a binder call with appropriate timing
- // return value is the uuid that the system generated for it.
- // the return value 0 and -1 are reserved.
- // -1 to indicate that there was a problem recording...
-
- Parcel data, reply;
- status_t err;
-
- if (item == NULL) {
- return MediaAnalyticsItem::SessionIDInvalid;
- }
-
- data.writeInterfaceToken(IMediaAnalyticsService::getInterfaceDescriptor());
- if(DEBUGGING_FLOW) {
- ALOGD("client offers record: %s", item->toString().c_str());
- }
- data.writeBool(forcenew);
- item->writeToParcel(&data);
-
- err = remote()->transact(SUBMIT_ITEM, data, &reply);
- if (err != NO_ERROR) {
- return MediaAnalyticsItem::SessionIDInvalid;
- }
-
- // get an answer out of 'reply'
- int64_t sessionid = reply.readInt64();
- if (DEBUGGING_RETURNS) {
- ALOGD("the caller gets sessionid=%" PRId64 "", sessionid);
- }
- return sessionid;
- }
-
-};
-
-IMPLEMENT_META_INTERFACE(MediaAnalyticsService, "android.media.IMediaAnalyticsService");
-
-// ----------------------------------------------------------------------
-
-status_t BnMediaAnalyticsService::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-
-
- // get calling pid/tid
- IPCThreadState *ipc = IPCThreadState::self();
- int clientPid = ipc->getCallingPid();
- // permission checking
-
- if(DEBUGGING_FLOW) {
- ALOGD("running in service, code %d, pid %d; called from pid %d",
- code, getpid(), clientPid);
- }
-
- switch (code) {
-
- case GENERATE_UNIQUE_SESSIONID: {
- CHECK_INTERFACE(IMediaAnalyticsService, data, reply);
-
- MediaAnalyticsItem::SessionID_t sessionid = generateUniqueSessionID();
- reply->writeInt64(sessionid);
-
- return NO_ERROR;
- } break;
-
- case SUBMIT_ITEM: {
- CHECK_INTERFACE(IMediaAnalyticsService, data, reply);
-
- bool forcenew;
- MediaAnalyticsItem *item = new MediaAnalyticsItem;
-
- data.readBool(&forcenew);
- item->readFromParcel(data);
-
- item->setPid(clientPid);
-
- // submit() takes over ownership of 'item'
- MediaAnalyticsItem::SessionID_t sessionid = submit(item, forcenew);
- reply->writeInt64(sessionid);
-
- return NO_ERROR;
- } break;
-
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-} // namespace android
diff --git a/media/libmedia/MediaAnalyticsItem.cpp b/media/libmedia/MediaAnalyticsItem.cpp
deleted file mode 100644
index 229e747..0000000
--- a/media/libmedia/MediaAnalyticsItem.cpp
+++ /dev/null
@@ -1,867 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#undef LOG_TAG
-#define LOG_TAG "MediaAnalyticsItem"
-
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/Mutex.h>
-#include <utils/SortedVector.h>
-#include <utils/threads.h>
-
-#include <media/stagefright/foundation/AString.h>
-
-#include <binder/IServiceManager.h>
-#include <media/IMediaAnalyticsService.h>
-#include <media/MediaAnalyticsItem.h>
-
-namespace android {
-
-#define DEBUG_SERVICEACCESS 0
-#define DEBUG_API 0
-#define DEBUG_ALLOCATIONS 0
-
-// after this many failed attempts, we stop trying [from this process] and just say that
-// the service is off.
-#define SVC_TRIES 2
-
-// the few universal keys we have
-const MediaAnalyticsItem::Key MediaAnalyticsItem::kKeyAny = "any";
-const MediaAnalyticsItem::Key MediaAnalyticsItem::kKeyNone = "none";
-
-const char * const MediaAnalyticsItem::EnabledProperty = "media.metrics.enabled";
-const char * const MediaAnalyticsItem::EnabledPropertyPersist = "persist.media.metrics.enabled";
-const int MediaAnalyticsItem::EnabledProperty_default = 1;
-
-
-// access functions for the class
-MediaAnalyticsItem::MediaAnalyticsItem()
- : mPid(-1),
- mUid(-1),
- mSessionID(MediaAnalyticsItem::SessionIDNone),
- mTimestamp(0),
- mFinalized(0),
- mPropCount(0), mPropSize(0), mProps(NULL)
-{
- mKey = MediaAnalyticsItem::kKeyNone;
-}
-
-MediaAnalyticsItem::MediaAnalyticsItem(MediaAnalyticsItem::Key key)
- : mPid(-1),
- mUid(-1),
- mSessionID(MediaAnalyticsItem::SessionIDNone),
- mTimestamp(0),
- mFinalized(0),
- mPropCount(0), mPropSize(0), mProps(NULL)
-{
- if (DEBUG_ALLOCATIONS) {
- ALOGD("Allocate MediaAnalyticsItem @ %p", this);
- }
- mKey = key;
-}
-
-MediaAnalyticsItem::~MediaAnalyticsItem() {
- if (DEBUG_ALLOCATIONS) {
- ALOGD("Destroy MediaAnalyticsItem @ %p", this);
- }
- clear();
-}
-
-void MediaAnalyticsItem::clear() {
-
- // clean allocated storage from key
- mKey.clear();
-
- // clean various major parameters
- mSessionID = MediaAnalyticsItem::SessionIDNone;
-
- // clean attributes
- // contents of the attributes
- for (size_t i = 0 ; i < mPropSize; i++ ) {
- clearProp(&mProps[i]);
- }
- // the attribute records themselves
- if (mProps != NULL) {
- free(mProps);
- mProps = NULL;
- }
- mPropSize = 0;
- mPropCount = 0;
-
- return;
-}
-
-// make a deep copy of myself
-MediaAnalyticsItem *MediaAnalyticsItem::dup() {
- MediaAnalyticsItem *dst = new MediaAnalyticsItem(this->mKey);
-
- if (dst != NULL) {
- // key as part of constructor
- dst->mPid = this->mPid;
- dst->mUid = this->mUid;
- dst->mSessionID = this->mSessionID;
- dst->mTimestamp = this->mTimestamp;
- dst->mFinalized = this->mFinalized;
-
- // properties aka attributes
- dst->growProps(this->mPropCount);
- for(size_t i=0;i<mPropCount;i++) {
- copyProp(&dst->mProps[i], &this->mProps[i]);
- }
- dst->mPropCount = this->mPropCount;
- }
-
- return dst;
-}
-
-// so clients can send intermediate values to be overlaid later
-MediaAnalyticsItem &MediaAnalyticsItem::setFinalized(bool value) {
- mFinalized = value;
- return *this;
-}
-
-bool MediaAnalyticsItem::getFinalized() const {
- return mFinalized;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::setSessionID(MediaAnalyticsItem::SessionID_t id) {
- mSessionID = id;
- return *this;
-}
-
-MediaAnalyticsItem::SessionID_t MediaAnalyticsItem::getSessionID() const {
- return mSessionID;
-}
-
-MediaAnalyticsItem::SessionID_t MediaAnalyticsItem::generateSessionID() {
-
- if (mSessionID == SessionIDNone) {
- // get one from the server
- MediaAnalyticsItem::SessionID_t newid = SessionIDNone;
- sp<IMediaAnalyticsService> svc = getInstance();
- if (svc != NULL) {
- newid = svc->generateUniqueSessionID();
- }
- mSessionID = newid;
- }
-
- return mSessionID;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::clearSessionID() {
- mSessionID = MediaAnalyticsItem::SessionIDNone;
- return *this;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::setTimestamp(nsecs_t ts) {
- mTimestamp = ts;
- return *this;
-}
-
-nsecs_t MediaAnalyticsItem::getTimestamp() const {
- return mTimestamp;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::setPid(pid_t pid) {
- mPid = pid;
- return *this;
-}
-
-pid_t MediaAnalyticsItem::getPid() const {
- return mPid;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::setUid(uid_t uid) {
- mUid = uid;
- return *this;
-}
-
-uid_t MediaAnalyticsItem::getUid() const {
- return mUid;
-}
-
-// this key is for the overall record -- "codec", "player", "drm", etc
-MediaAnalyticsItem &MediaAnalyticsItem::setKey(MediaAnalyticsItem::Key key) {
- mKey = key;
- return *this;
-}
-
-MediaAnalyticsItem::Key MediaAnalyticsItem::getKey() {
- return mKey;
-}
-
-// number of attributes we have in this record
-int32_t MediaAnalyticsItem::count() const {
- return mPropCount;
-}
-
-// find the proper entry in the list
-size_t MediaAnalyticsItem::findPropIndex(const char *name, size_t len)
-{
- size_t i = 0;
- for (; i < mPropCount; i++) {
- Prop *prop = &mProps[i];
- if (prop->mNameLen != len) {
- continue;
- }
- if (memcmp(name, prop->mName, len) == 0) {
- break;
- }
- }
- return i;
-}
-
-MediaAnalyticsItem::Prop *MediaAnalyticsItem::findProp(const char *name) {
- size_t len = strlen(name);
- size_t i = findPropIndex(name, len);
- if (i < mPropCount) {
- return &mProps[i];
- }
- return NULL;
-}
-
-void MediaAnalyticsItem::Prop::setName(const char *name, size_t len) {
- mNameLen = len;
- mName = (const char *) malloc(len+1);
- memcpy ((void *)mName, name, len+1);
-}
-
-// used only as part of a storing operation
-MediaAnalyticsItem::Prop *MediaAnalyticsItem::allocateProp(const char *name) {
- size_t len = strlen(name);
- size_t i = findPropIndex(name, len);
- Prop *prop;
-
- if (i < mPropCount) {
- prop = &mProps[i];
- } else {
- if (i == mPropSize) {
- growProps();
- // XXX: verify success
- }
- i = mPropCount++;
- prop = &mProps[i];
- prop->setName(name, len);
- }
-
- return prop;
-}
-
-// set the values
-void MediaAnalyticsItem::setInt32(MediaAnalyticsItem::Attr name, int32_t value) {
- Prop *prop = allocateProp(name);
- prop->mType = kTypeInt32;
- prop->u.int32Value = value;
-}
-
-void MediaAnalyticsItem::setInt64(MediaAnalyticsItem::Attr name, int64_t value) {
- Prop *prop = allocateProp(name);
- prop->mType = kTypeInt64;
- prop->u.int64Value = value;
-}
-
-void MediaAnalyticsItem::setDouble(MediaAnalyticsItem::Attr name, double value) {
- Prop *prop = allocateProp(name);
- prop->mType = kTypeDouble;
- prop->u.doubleValue = value;
-}
-
-void MediaAnalyticsItem::setCString(MediaAnalyticsItem::Attr name, const char *value) {
-
- Prop *prop = allocateProp(name);
- // any old value will be gone
- prop->mType = kTypeCString;
- prop->u.CStringValue = strdup(value);
-}
-
-void MediaAnalyticsItem::setRate(MediaAnalyticsItem::Attr name, int64_t count, int64_t duration) {
- Prop *prop = allocateProp(name);
- prop->mType = kTypeRate;
- prop->u.rate.count = count;
- prop->u.rate.duration = duration;
-}
-
-
-// find/add/set fused into a single operation
-void MediaAnalyticsItem::addInt32(MediaAnalyticsItem::Attr name, int32_t value) {
- Prop *prop = allocateProp(name);
- switch (prop->mType) {
- case kTypeInt32:
- prop->u.int32Value += value;
- break;
- default:
- clearPropValue(prop);
- prop->mType = kTypeInt32;
- prop->u.int32Value = value;
- break;
- }
-}
-
-void MediaAnalyticsItem::addInt64(MediaAnalyticsItem::Attr name, int64_t value) {
- Prop *prop = allocateProp(name);
- switch (prop->mType) {
- case kTypeInt64:
- prop->u.int64Value += value;
- break;
- default:
- clearPropValue(prop);
- prop->mType = kTypeInt64;
- prop->u.int64Value = value;
- break;
- }
-}
-
-void MediaAnalyticsItem::addRate(MediaAnalyticsItem::Attr name, int64_t count, int64_t duration) {
- Prop *prop = allocateProp(name);
- switch (prop->mType) {
- case kTypeRate:
- prop->u.rate.count += count;
- prop->u.rate.duration += duration;
- break;
- default:
- clearPropValue(prop);
- prop->mType = kTypeRate;
- prop->u.rate.count = count;
- prop->u.rate.duration = duration;
- break;
- }
-}
-
-void MediaAnalyticsItem::addDouble(MediaAnalyticsItem::Attr name, double value) {
- Prop *prop = allocateProp(name);
- switch (prop->mType) {
- case kTypeDouble:
- prop->u.doubleValue += value;
- break;
- default:
- clearPropValue(prop);
- prop->mType = kTypeDouble;
- prop->u.doubleValue = value;
- break;
- }
-}
-
-// find & extract values
-bool MediaAnalyticsItem::getInt32(MediaAnalyticsItem::Attr name, int32_t *value) {
- Prop *prop = findProp(name);
- if (prop == NULL || prop->mType != kTypeInt32) {
- return false;
- }
- if (value != NULL) {
- *value = prop->u.int32Value;
- }
- return true;
-}
-
-bool MediaAnalyticsItem::getInt64(MediaAnalyticsItem::Attr name, int64_t *value) {
- Prop *prop = findProp(name);
- if (prop == NULL || prop->mType != kTypeInt64) {
- return false;
- }
- if (value != NULL) {
- *value = prop->u.int64Value;
- }
- return true;
-}
-
-bool MediaAnalyticsItem::getRate(MediaAnalyticsItem::Attr name, int64_t *count, int64_t *duration, double *rate) {
- Prop *prop = findProp(name);
- if (prop == NULL || prop->mType != kTypeRate) {
- return false;
- }
- if (count != NULL) {
- *count = prop->u.rate.count;
- }
- if (duration != NULL) {
- *duration = prop->u.rate.duration;
- }
- if (rate != NULL) {
- double r = 0.0;
- if (prop->u.rate.duration != 0) {
- r = prop->u.rate.count / (double) prop->u.rate.duration;
- }
- *rate = r;
- }
- return true;
-}
-
-bool MediaAnalyticsItem::getDouble(MediaAnalyticsItem::Attr name, double *value) {
- Prop *prop = findProp(name);
- if (prop == NULL || prop->mType != kTypeDouble) {
- return false;
- }
- if (value != NULL) {
- *value = prop->u.doubleValue;
- }
- return true;
-}
-
-// caller responsible for the returned string
-bool MediaAnalyticsItem::getCString(MediaAnalyticsItem::Attr name, char **value) {
- Prop *prop = findProp(name);
- if (prop == NULL || prop->mType != kTypeDouble) {
- return false;
- }
- if (value != NULL) {
- *value = strdup(prop->u.CStringValue);
- }
- return true;
-}
-
-// remove indicated keys and their values
-// return value is # keys removed
-int32_t MediaAnalyticsItem::filter(int n, MediaAnalyticsItem::Attr attrs[]) {
- int zapped = 0;
- if (attrs == NULL || n <= 0) {
- return -1;
- }
- for (ssize_t i = 0 ; i < n ; i++) {
- const char *name = attrs[i];
- size_t len = strlen(name);
- size_t j = findPropIndex(name, len);
- if (j >= mPropCount) {
- // not there
- continue;
- } else if (j+1 == mPropCount) {
- // last one, shorten
- zapped++;
- clearProp(&mProps[j]);
- mPropCount--;
- } else {
- // in the middle, bring last one down and shorten
- zapped++;
- clearProp(&mProps[j]);
- mProps[j] = mProps[mPropCount-1];
- mPropCount--;
- }
- }
- return zapped;
-}
-
-// remove any keys NOT in the provided list
-// return value is # keys removed
-int32_t MediaAnalyticsItem::filterNot(int n, MediaAnalyticsItem::Attr attrs[]) {
- int zapped = 0;
- if (attrs == NULL || n <= 0) {
- return -1;
- }
- for (ssize_t i = mPropCount-1 ; i >=0 ; i--) {
- Prop *prop = &mProps[i];
- for (ssize_t j = 0; j < n ; j++) {
- if (strcmp(prop->mName, attrs[j]) == 0) {
- clearProp(prop);
- zapped++;
- if (i != (ssize_t)(mPropCount-1)) {
- *prop = mProps[mPropCount-1];
- }
- initProp(&mProps[mPropCount-1]);
- mPropCount--;
- break;
- }
- }
- }
- return zapped;
-}
-
-// remove a single key
-// return value is 0 (not found) or 1 (found and removed)
-int32_t MediaAnalyticsItem::filter(MediaAnalyticsItem::Attr name) {
- return filter(1, &name);
-}
-
-// handle individual items/properties stored within the class
-//
-
-void MediaAnalyticsItem::initProp(Prop *prop) {
- if (prop != NULL) {
- prop->mName = NULL;
- prop->mNameLen = 0;
-
- prop->mType = kTypeNone;
- }
-}
-
-void MediaAnalyticsItem::clearProp(Prop *prop)
-{
- if (prop != NULL) {
- if (prop->mName != NULL) {
- free((void *)prop->mName);
- prop->mName = NULL;
- prop->mNameLen = 0;
- }
-
- clearPropValue(prop);
- }
-}
-
-void MediaAnalyticsItem::clearPropValue(Prop *prop)
-{
- if (prop != NULL) {
- if (prop->mType == kTypeCString && prop->u.CStringValue != NULL) {
- free(prop->u.CStringValue);
- prop->u.CStringValue = NULL;
- }
- prop->mType = kTypeNone;
- }
-}
-
-void MediaAnalyticsItem::copyProp(Prop *dst, const Prop *src)
-{
- // get rid of any pointers in the dst
- clearProp(dst);
-
- *dst = *src;
-
- // fix any pointers that we blindly copied, so we have our own copies
- if (dst->mName) {
- void *p = malloc(dst->mNameLen + 1);
- memcpy (p, src->mName, dst->mNameLen + 1);
- dst->mName = (const char *) p;
- }
- if (dst->mType == kTypeCString) {
- dst->u.CStringValue = strdup(src->u.CStringValue);
- }
-}
-
-void MediaAnalyticsItem::growProps(int increment)
-{
- if (increment <= 0) {
- increment = kGrowProps;
- }
- int nsize = mPropSize + increment;
- Prop *ni = (Prop *)realloc(mProps, sizeof(Prop) * nsize);
-
- if (ni != NULL) {
- for (int i = mPropSize; i < nsize; i++) {
- initProp(&ni[i]);
- }
- mProps = ni;
- mPropSize = nsize;
- }
-}
-
-// Parcel / serialize things for binder calls
-//
-
-int32_t MediaAnalyticsItem::readFromParcel(const Parcel& data) {
- // into 'this' object
- // .. we make a copy of the string to put away.
- mKey = data.readCString();
- mSessionID = data.readInt64();
- mFinalized = data.readInt32();
- mTimestamp = data.readInt64();
-
- int count = data.readInt32();
- for (int i = 0; i < count ; i++) {
- MediaAnalyticsItem::Attr attr = data.readCString();
- int32_t ztype = data.readInt32();
- switch (ztype) {
- case MediaAnalyticsItem::kTypeInt32:
- setInt32(attr, data.readInt32());
- break;
- case MediaAnalyticsItem::kTypeInt64:
- setInt64(attr, data.readInt64());
- break;
- case MediaAnalyticsItem::kTypeDouble:
- setDouble(attr, data.readDouble());
- break;
- case MediaAnalyticsItem::kTypeCString:
- setCString(attr, data.readCString());
- break;
- case MediaAnalyticsItem::kTypeRate:
- {
- int64_t count = data.readInt64();
- int64_t duration = data.readInt64();
- setRate(attr, count, duration);
- }
- break;
- default:
- ALOGE("reading bad item type: %d, idx %d",
- ztype, i);
- return -1;
- }
- }
-
- return 0;
-}
-
-int32_t MediaAnalyticsItem::writeToParcel(Parcel *data) {
- if (data == NULL) return -1;
-
-
- data->writeCString(mKey.c_str());
- data->writeInt64(mSessionID);
- data->writeInt32(mFinalized);
- data->writeInt64(mTimestamp);
-
- // set of items
- int count = mPropCount;
- data->writeInt32(count);
- for (int i = 0 ; i < count; i++ ) {
- Prop *prop = &mProps[i];
- data->writeCString(prop->mName);
- data->writeInt32(prop->mType);
- switch (prop->mType) {
- case MediaAnalyticsItem::kTypeInt32:
- data->writeInt32(prop->u.int32Value);
- break;
- case MediaAnalyticsItem::kTypeInt64:
- data->writeInt64(prop->u.int64Value);
- break;
- case MediaAnalyticsItem::kTypeDouble:
- data->writeDouble(prop->u.doubleValue);
- break;
- case MediaAnalyticsItem::kTypeRate:
- data->writeInt64(prop->u.rate.count);
- data->writeInt64(prop->u.rate.duration);
- break;
- case MediaAnalyticsItem::kTypeCString:
- data->writeCString(prop->u.CStringValue);
- break;
- default:
- ALOGE("found bad Prop type: %d, idx %d, name %s",
- prop->mType, i, prop->mName);
- break;
- }
- }
-
- return 0;
-}
-
-
-AString MediaAnalyticsItem::toString() {
-
- AString result = "(";
- char buffer[512];
-
- // 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);
- result.append(buffer);
-
- snprintf(buffer, sizeof(buffer), "%d:", mFinalized);
- result.append(buffer);
- snprintf(buffer, sizeof(buffer), "%" PRId64 ":", mTimestamp);
- result.append(buffer);
-
- // set of items
- int count = mPropCount;
- snprintf(buffer, sizeof(buffer), "%d:", count);
- result.append(buffer);
- for (int i = 0 ; i < count; i++ ) {
- Prop *prop = &mProps[i];
- switch (prop->mType) {
- case MediaAnalyticsItem::kTypeInt32:
- snprintf(buffer,sizeof(buffer),
- "%s=%d:", prop->mName, prop->u.int32Value);
- break;
- case MediaAnalyticsItem::kTypeInt64:
- snprintf(buffer,sizeof(buffer),
- "%s=%" PRId64 ":", prop->mName, prop->u.int64Value);
- break;
- case MediaAnalyticsItem::kTypeDouble:
- snprintf(buffer,sizeof(buffer),
- "%s=%e:", prop->mName, prop->u.doubleValue);
- break;
- case MediaAnalyticsItem::kTypeRate:
- snprintf(buffer,sizeof(buffer),
- "%s=%" PRId64 "/%" PRId64 ":", prop->mName,
- prop->u.rate.count, prop->u.rate.duration);
- break;
- case MediaAnalyticsItem::kTypeCString:
- snprintf(buffer,sizeof(buffer), "%s=", prop->mName);
- result.append(buffer);
- // XXX: sanitize string for ':' '='
- result.append(prop->u.CStringValue);
- buffer[0] = ':';
- buffer[1] = '\0';
- break;
- default:
- ALOGE("to_String bad item type: %d for %s",
- prop->mType, prop->mName);
- break;
- }
- result.append(buffer);
- }
-
- result.append(")");
-
- return result;
-}
-
-// for the lazy, we offer methods that finds the service and
-// calls the appropriate daemon
-bool MediaAnalyticsItem::selfrecord() {
- return selfrecord(false);
-}
-
-bool MediaAnalyticsItem::selfrecord(bool forcenew) {
-
- if (DEBUG_API) {
- AString p = this->toString();
- ALOGD("selfrecord of: %s [forcenew=%d]", p.c_str(), forcenew);
- }
-
- sp<IMediaAnalyticsService> svc = getInstance();
-
- if (svc != NULL) {
- svc->submit(this, forcenew);
- return true;
- } else {
- AString p = this->toString();
- ALOGD("Unable to record: %s [forcenew=%d]", p.c_str(), forcenew);
- return false;
- }
-}
-
-// get a connection we can reuse for most of our lifetime
-// static
-sp<IMediaAnalyticsService> MediaAnalyticsItem::sAnalyticsService;
-static Mutex sInitMutex;
-
-//static
-bool MediaAnalyticsItem::isEnabled() {
- int enabled = property_get_int32(MediaAnalyticsItem::EnabledProperty, -1);
-
- if (enabled == -1) {
- enabled = property_get_int32(MediaAnalyticsItem::EnabledPropertyPersist, -1);
- }
- if (enabled == -1) {
- enabled = MediaAnalyticsItem::EnabledProperty_default;
- }
- if (enabled <= 0) {
- return false;
- }
- return true;
-}
-
-//static
-sp<IMediaAnalyticsService> MediaAnalyticsItem::getInstance() {
- static const char *servicename = "media.metrics";
- static int tries_remaining = SVC_TRIES;
- int enabled = isEnabled();
-
- if (enabled == false) {
- if (DEBUG_SERVICEACCESS) {
- ALOGD("disabled");
- }
- return NULL;
- }
-
- {
- Mutex::Autolock _l(sInitMutex);
- const char *badness = "";
-
- // think of tries_remaining as telling us whether service==NULL because
- // (1) we haven't tried to initialize it yet
- // (2) we've tried to initialize it, but failed.
- if (sAnalyticsService == NULL && tries_remaining > 0) {
- sp<IServiceManager> sm = defaultServiceManager();
- if (sm != NULL) {
- sp<IBinder> binder = sm->getService(String16(servicename));
- if (binder != NULL) {
- sAnalyticsService = interface_cast<IMediaAnalyticsService>(binder);
- } else {
- badness = "did not find service";
- }
- } else {
- badness = "No Service Manager access";
- }
-
- if (sAnalyticsService == NULL) {
- if (tries_remaining > 0) {
- tries_remaining--;
- }
- if (DEBUG_SERVICEACCESS) {
- ALOGD("Unable to bind to service %s: %s", servicename, badness);
- }
- }
- }
-
- return sAnalyticsService;
- }
-}
-
-
-// merge the info from 'incoming' into this record.
-// we finish with a union of this+incoming and special handling for collisions
-bool MediaAnalyticsItem::merge(MediaAnalyticsItem *incoming) {
-
- // if I don't have key or session id, take them from incoming
- // 'this' should never be missing both of them...
- if (mKey.empty()) {
- mKey = incoming->mKey;
- } else if (mSessionID == 0) {
- mSessionID = incoming->mSessionID;
- }
-
- // we always take the more recent 'finalized' value
- setFinalized(incoming->getFinalized());
-
- // for each attribute from 'incoming', resolve appropriately
- int nattr = incoming->mPropCount;
- for (int i = 0 ; i < nattr; i++ ) {
- Prop *iprop = &incoming->mProps[i];
- Prop *oprop = findProp(iprop->mName);
- const char *p = iprop->mName;
- size_t len = strlen(p);
- char semantic = p[len-1];
-
- if (oprop == NULL) {
- // no oprop, so we insert the new one
- oprop = allocateProp(p);
- copyProp(oprop, iprop);
- } else {
- // merge iprop into oprop
- switch (semantic) {
- case '<': // first aka keep old)
- /* nop */
- break;
-
- default: // default is 'last'
- case '>': // last (aka keep new)
- copyProp(oprop, iprop);
- break;
-
- case '+': /* sum */
- // XXX validate numeric types, sum in place
- break;
-
- }
- }
- }
-
- // not sure when we'd return false...
- return true;
-}
-
-} // namespace android
-
diff --git a/media/libmedia/include/IMediaAnalyticsService.h b/media/libmedia/include/IMediaAnalyticsService.h
deleted file mode 100644
index f635e94..0000000
--- a/media/libmedia/include/IMediaAnalyticsService.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IMEDIAANALYTICSSERVICE_H
-#define ANDROID_IMEDIAANALYTICSSERVICE_H
-
-#include <utils/String8.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-#include <sys/types.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/RefBase.h>
-#include <utils/List.h>
-
-#include <binder/IServiceManager.h>
-
-#include <media/MediaAnalyticsItem.h>
-// nope...#include <media/MediaAnalytics.h>
-
-namespace android {
-
-class IMediaAnalyticsService: public IInterface
-{
-public:
- DECLARE_META_INTERFACE(MediaAnalyticsService);
-
- // generate a unique sessionID to use across multiple requests
- // 'unique' is within this device, since last reboot
- virtual MediaAnalyticsItem::SessionID_t generateUniqueSessionID() = 0;
-
- // submit the indicated record to the mediaanalytics service, where
- // it will be merged (if appropriate) with incomplete records that
- // share the same key and sessionid.
- // 'forcenew' marks any matching incomplete record as complete before
- // inserting this new record.
- // returns the sessionID associated with that item.
- // caller continues to own the passed item
- virtual MediaAnalyticsItem::SessionID_t submit(MediaAnalyticsItem *item, bool forcenew) = 0;
-
-};
-
-// ----------------------------------------------------------------------------
-
-class BnMediaAnalyticsService: public BnInterface<IMediaAnalyticsService>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IMEDIASTATISTICSSERVICE_H
diff --git a/media/libmedia/include/MediaAnalyticsItem.h b/media/libmedia/include/MediaAnalyticsItem.h
deleted file mode 100644
index f050e7f..0000000
--- a/media/libmedia/include/MediaAnalyticsItem.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_MEDIA_MEDIAANALYTICSITEM_H
-#define ANDROID_MEDIA_MEDIAANALYTICSITEM_H
-
-#include <cutils/properties.h>
-#include <sys/types.h>
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-#include <utils/StrongPointer.h>
-#include <utils/Timers.h>
-
-#include <media/stagefright/foundation/AString.h>
-
-namespace android {
-
-
-
-class IMediaAnalyticsService;
-
-// the class interface
-//
-
-class MediaAnalyticsItem {
-
- friend class MediaAnalyticsService;
- friend class IMediaAnalyticsService;
- friend class MediaMetricsJNI;
-
- public:
-
- enum Type {
- kTypeNone = 0,
- kTypeInt32 = 1,
- kTypeInt64 = 2,
- kTypeDouble = 3,
- kTypeCString = 4,
- kTypeRate = 5,
- };
-
- // sessionid
- // unique within device, within boot,
- typedef int64_t SessionID_t;
- static constexpr SessionID_t SessionIDInvalid = -1;
- static constexpr SessionID_t SessionIDNone = 0;
-
- // Key: the record descriminator
- // values for the record discriminator
- // values can be "component/component"
- // basic values: "video", "audio", "drm"
- // XXX: need to better define the format
- typedef AString Key;
- static const Key kKeyNone; // ""
- static const Key kKeyAny; // "*"
-
- // Attr: names for attributes within a record
- // format "prop1" or "prop/subprop"
- // XXX: need to better define the format
- typedef const char *Attr;
-
-
- public:
-
- // access functions for the class
- MediaAnalyticsItem();
- MediaAnalyticsItem(Key);
- ~MediaAnalyticsItem();
-
- // so clients can send intermediate values to be overlaid later
- MediaAnalyticsItem &setFinalized(bool);
- bool getFinalized() const;
-
- // SessionID ties multiple submissions for same key together
- // so that if video "height" and "width" are known at one point
- // and "framerate" is only known later, they can be be brought
- // together.
- MediaAnalyticsItem &setSessionID(SessionID_t);
- MediaAnalyticsItem &clearSessionID();
- SessionID_t getSessionID() const;
- // generates and stores a new ID iff mSessionID == SessionIDNone
- SessionID_t generateSessionID();
-
- // reset all contents, discarding any extra data
- void clear();
- MediaAnalyticsItem *dup();
-
- // set the key discriminator for the record.
- // most often initialized as part of the constructor
- MediaAnalyticsItem &setKey(MediaAnalyticsItem::Key);
- MediaAnalyticsItem::Key getKey();
-
- // # of attributes in the record
- int32_t count() const;
-
- // set values appropriately
- void setInt32(Attr, int32_t value);
- void setInt64(Attr, int64_t value);
- void setDouble(Attr, double value);
- void setRate(Attr, int64_t count, int64_t duration);
- void setCString(Attr, const char *value);
-
- // fused get/add/set; if attr wasn't there, it's a simple set.
- // type-mismatch counts as "wasn't there".
- void addInt32(Attr, int32_t value);
- void addInt64(Attr, int64_t value);
- void addDouble(Attr, double value);
- void addRate(Attr, int64_t count, int64_t duration);
-
- // find & extract values
- // return indicates whether attr exists (and thus value filled in)
- // NULL parameter value suppresses storage of value.
- bool getInt32(Attr, int32_t *value);
- bool getInt64(Attr, int64_t *value);
- bool getDouble(Attr, double *value);
- bool getRate(Attr, int64_t *count, int64_t *duration, double *rate);
- // Caller owns the returned string
- bool getCString(Attr, char **value);
-
- // parameter indicates whether to close any existing open
- // record with same key before establishing a new record
- // caller retains ownership of 'this'.
- bool selfrecord(bool);
- bool selfrecord();
-
- // remove indicated attributes and their values
- // filterNot() could also be called keepOnly()
- // return value is # attributes removed
- // XXX: perhaps 'remove' instead of 'filter'
- // XXX: filterNot would become 'keep'
- int32_t filter(int count, Attr attrs[]);
- int32_t filterNot(int count, Attr attrs[]);
- int32_t filter(Attr attr);
-
- // below here are used on server side or to talk to server
- // clients need not worry about these.
-
- // timestamp, pid, and uid only used on server side
- // timestamp is in 'nanoseconds, unix time'
- MediaAnalyticsItem &setTimestamp(nsecs_t);
- nsecs_t getTimestamp() const;
-
- MediaAnalyticsItem &setPid(pid_t);
- pid_t getPid() const;
-
- MediaAnalyticsItem &setUid(uid_t);
- uid_t getUid() const;
-
- // our serialization code for binder calls
- int32_t writeToParcel(Parcel *);
- int32_t readFromParcel(const Parcel&);
-
- AString toString();
-
- // are we collecting analytics data
- static bool isEnabled();
-
- protected:
-
- // merge fields from arg into this
- // with rules for first/last/add, etc
- // XXX: document semantics and how they are indicated
- // caller continues to own 'incoming'
- bool merge(MediaAnalyticsItem *incoming);
-
- // enabled 1, disabled 0
- static const char * const EnabledProperty;
- static const char * const EnabledPropertyPersist;
- static const int EnabledProperty_default;
-
- private:
-
- // to help validate that A doesn't mess with B's records
- pid_t mPid;
- uid_t mUid;
-
- // let's reuse a binder connection
- static sp<IMediaAnalyticsService> sAnalyticsService;
- static sp<IMediaAnalyticsService> getInstance();
-
- // tracking information
- SessionID_t mSessionID; // grouping similar records
- nsecs_t mTimestamp; // ns, system_time_monotonic
-
- // will this record accept further updates
- bool mFinalized;
-
- Key mKey;
-
- struct Prop {
-
- Type mType;
- const char *mName;
- size_t mNameLen; // the strlen(), doesn't include the null
- union {
- int32_t int32Value;
- int64_t int64Value;
- double doubleValue;
- char *CStringValue;
- struct { int64_t count, duration; } rate;
- } u;
- void setName(const char *name, size_t len);
- };
-
- void initProp(Prop *item);
- void clearProp(Prop *item);
- void clearPropValue(Prop *item);
- void copyProp(Prop *dst, const Prop *src);
- enum {
- kGrowProps = 10
- };
- void growProps(int increment = kGrowProps);
- size_t findPropIndex(const char *name, size_t len);
- Prop *findProp(const char *name);
- Prop *allocateProp(const char *name);
-
- size_t mPropCount;
- size_t mPropSize;
- Prop *mProps;
-
-};
-
-} // namespace android
-
-#endif