diff --git a/media/libmedia/MediaAnalyticsItem.cpp b/media/libmedia/MediaAnalyticsItem.cpp
new file mode 100644
index 0000000..5f05d5a
--- /dev/null
+++ b/media/libmedia/MediaAnalyticsItem.cpp
@@ -0,0 +1,703 @@
+/*
+ * 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 <sys/types.h>
+#include <inttypes.h>
+
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.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
+
+// the few universal keys we have
+const MediaAnalyticsItem::Key MediaAnalyticsItem::kKeyAny  = "any";
+const MediaAnalyticsItem::Key MediaAnalyticsItem::kKeyNone  = "none";
+
+const char * const MediaAnalyticsItem::EnabledProperty  = "media.analytics.enabled";
+const char * const MediaAnalyticsItem::EnabledPropertyPersist  = "persist.media.analytics.enabled";
+const int MediaAnalyticsItem::EnabledProperty_default  = 0;
+
+
+// access functions for the class
+MediaAnalyticsItem::MediaAnalyticsItem()
+    : RefBase(),
+      mPid(0),
+      mUid(0),
+      mSessionID(MediaAnalyticsItem::SessionIDNone),
+      mTimestamp(0),
+      mFinalized(0) {
+    mKey = MediaAnalyticsItem::kKeyNone;
+}
+
+MediaAnalyticsItem::MediaAnalyticsItem(MediaAnalyticsItem::Key key)
+    : RefBase(),
+      mPid(0),
+      mUid(0),
+      mSessionID(MediaAnalyticsItem::SessionIDNone),
+      mTimestamp(0),
+      mFinalized(0) {
+    mKey = key;
+}
+
+MediaAnalyticsItem::~MediaAnalyticsItem() {
+    clear();
+}
+
+// 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() {
+    MediaAnalyticsItem::SessionID_t newid = SessionIDNone;
+    ALOGD("generateSessionID()");
+
+    if (mSessionID == SessionIDNone) {
+        // get one from the server
+        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;
+}
+
+void MediaAnalyticsItem::clear() {
+
+    mKey.clear();
+
+#if 0
+    // not sure that I need to (or should) be doing this...
+    // seeing some strangeness in some records
+    int count = mItems.size();
+    for (int i = 0 ; i < count; i++ ) {
+        MediaAnalyticsItem::Attr attr = mItems.keyAt(i);
+        const sp<Item> value = mItems.valueAt(i);
+        value->clear();
+        attr.clear();
+    }
+    mItems.clear();
+#endif
+
+    return;
+}
+
+// this key is for the overall record -- "vid" or "aud"
+// assuming for the moment we use int32_t like the
+// media frameworks MetaData.cpp
+MediaAnalyticsItem &MediaAnalyticsItem::setKey(MediaAnalyticsItem::Key key) {
+    // XXX: possible validation of legal keys.
+    mKey = key;
+    return *this;
+}
+
+MediaAnalyticsItem::Key MediaAnalyticsItem::getKey() {
+    return mKey;
+}
+
+// number of keys we have in our dictionary
+// we won't upload empty records
+int32_t MediaAnalyticsItem::count() const {
+    return mItems.size();
+}
+
+// set the values
+bool MediaAnalyticsItem::setInt32(MediaAnalyticsItem::Attr attr, int32_t value) {
+    ssize_t i = mItems.indexOfKey(attr);
+    bool overwrote = true;
+    if (i<0) {
+        sp<Item> item = new Item();
+        i = mItems.add(attr, item);
+        overwrote = false;
+    }
+    sp<Item> &item = mItems.editValueAt(i);
+    item->mType = MediaAnalyticsItem::Item::kTypeInt32;
+    item->u.int32Value = value;
+    return overwrote;
+}
+
+bool MediaAnalyticsItem::setInt64(MediaAnalyticsItem::Attr attr, int64_t value) {
+    ssize_t i = mItems.indexOfKey(attr);
+    bool overwrote = true;
+    if (i<0) {
+        sp<Item> item = new Item();
+        i = mItems.add(attr, item);
+        overwrote = false;
+    }
+    sp<Item> &item = mItems.editValueAt(i);
+    item->mType = MediaAnalyticsItem::Item::kTypeInt64;
+    item->u.int64Value = value;
+    return overwrote;
+}
+
+bool MediaAnalyticsItem::setDouble(MediaAnalyticsItem::Attr attr, double value) {
+    ssize_t i = mItems.indexOfKey(attr);
+    bool overwrote = true;
+    if (i<0) {
+        sp<Item> item = new Item();
+        i = mItems.add(attr, item);
+        overwrote = false;
+    }
+    sp<Item> &item = mItems.editValueAt(i);
+    item->mType = MediaAnalyticsItem::Item::kTypeDouble;
+    item->u.doubleValue = value;
+    return overwrote;
+}
+
+bool MediaAnalyticsItem::setCString(MediaAnalyticsItem::Attr attr, const char *value) {
+    bool overwrote = true;
+    if (value == NULL) return false;
+    // we store our own copy of the supplied string
+    char *nvalue = strdup(value);
+    if (nvalue == NULL) {
+            return false;
+    }
+    ssize_t i = mItems.indexOfKey(attr);
+    if (i<0) {
+        sp<Item> item = new Item();
+        i = mItems.add(attr, item);
+        overwrote = false;
+    }
+    sp<Item> &item = mItems.editValueAt(i);
+    if (item->mType == MediaAnalyticsItem::Item::kTypeCString
+        && item->u.CStringValue != NULL) {
+            free(item->u.CStringValue);
+            item->u.CStringValue = NULL;
+    }
+    item->mType = MediaAnalyticsItem::Item::kTypeCString;
+    item->u.CStringValue = nvalue;
+    return true;
+}
+
+// find/add/set fused into a single operation
+bool MediaAnalyticsItem::addInt32(MediaAnalyticsItem::Attr attr, int32_t value) {
+    ssize_t i = mItems.indexOfKey(attr);
+    bool overwrote = true;
+    if (i<0) {
+        sp<Item> item = new Item();
+        i = mItems.add(attr, item);
+        overwrote = false;
+    }
+    sp<Item> &item = mItems.editValueAt(i);
+    if (overwrote
+        && item->mType == MediaAnalyticsItem::Item::kTypeInt32) {
+        item->u.int32Value += value;
+    } else {
+        // start clean if there was a type mismatch
+        item->u.int32Value = value;
+    }
+    item->mType = MediaAnalyticsItem::Item::kTypeInt32;
+    return overwrote;
+}
+
+bool MediaAnalyticsItem::addInt64(MediaAnalyticsItem::Attr attr, int64_t value) {
+    ssize_t i = mItems.indexOfKey(attr);
+    bool overwrote = true;
+    if (i<0) {
+        sp<Item> item = new Item();
+        i = mItems.add(attr, item);
+        overwrote = false;
+    }
+    sp<Item> &item = mItems.editValueAt(i);
+    if (overwrote
+        && item->mType == MediaAnalyticsItem::Item::kTypeInt64) {
+        item->u.int64Value += value;
+    } else {
+        // start clean if there was a type mismatch
+        item->u.int64Value = value;
+    }
+    item->mType = MediaAnalyticsItem::Item::kTypeInt64;
+    return overwrote;
+}
+
+bool MediaAnalyticsItem::addDouble(MediaAnalyticsItem::Attr attr, double value) {
+    ssize_t i = mItems.indexOfKey(attr);
+    bool overwrote = true;
+    if (i<0) {
+        sp<Item> item = new Item();
+        i = mItems.add(attr, item);
+        overwrote = false;
+    }
+    sp<Item> &item = mItems.editValueAt(i);
+    if (overwrote
+        && item->mType == MediaAnalyticsItem::Item::kTypeDouble) {
+        item->u.doubleValue += value;
+    } else {
+        // start clean if there was a type mismatch
+        item->u.doubleValue = value;
+    }
+    item->mType = MediaAnalyticsItem::Item::kTypeDouble;
+    return overwrote;
+}
+
+// find & extract values
+bool MediaAnalyticsItem::getInt32(MediaAnalyticsItem::Attr attr, int32_t *value) {
+    ssize_t i = mItems.indexOfKey(attr);
+    if (i < 0) {
+        return false;
+    }
+    sp<Item> &item = mItems.editValueAt(i);
+    *value = item->u.int32Value;
+    return true;
+}
+bool MediaAnalyticsItem::getInt64(MediaAnalyticsItem::Attr attr, int64_t *value) {
+    ssize_t i = mItems.indexOfKey(attr);
+    if (i < 0) {
+        return false;
+    }
+    sp<Item> &item = mItems.editValueAt(i);
+    *value = item->u.int64Value;
+    return true;
+}
+bool MediaAnalyticsItem::getDouble(MediaAnalyticsItem::Attr attr, double *value) {
+    ssize_t i = mItems.indexOfKey(attr);
+    if (i < 0) {
+        return false;
+    }
+    sp<Item> &item = mItems.editValueAt(i);
+    *value = item->u.doubleValue;
+    return true;
+}
+
+// caller responsible for the returned string
+bool MediaAnalyticsItem::getCString(MediaAnalyticsItem::Attr attr, char **value) {
+    ssize_t i = mItems.indexOfKey(attr);
+    if (i < 0) {
+        return false;
+    }
+    sp<Item> &item = mItems.editValueAt(i);
+    char *p = strdup(item->u.CStringValue);
+    *value = p;
+    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) {
+        return -1;
+    }
+    if (n <= 0) {
+        return -1;
+    }
+    for (ssize_t i = 0 ; i < n ;  i++) {
+        ssize_t j = mItems.indexOfKey(attrs[i]);
+        if (j >= 0) {
+            mItems.removeItemsAt(j);
+            zapped++;
+        }
+    }
+    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) {
+        return -1;
+    }
+    if (n <= 0) {
+        return -1;
+    }
+    for (ssize_t i = mItems.size()-1 ; i >=0 ;  i--) {
+        const MediaAnalyticsItem::Attr& lattr = mItems.keyAt(i);
+        ssize_t j;
+        for (j= 0; j < n ; j++) {
+            if (lattr == attrs[j]) {
+                mItems.removeItemsAt(i);
+                zapped++;
+                break;
+            }
+        }
+    }
+    return zapped;
+}
+
+// remove a single key
+// return value is 0 (not found) or 1 (found and removed)
+int32_t MediaAnalyticsItem::filter(MediaAnalyticsItem::Attr attr) {
+    if (attr == 0) return -1;
+    ssize_t i = mItems.indexOfKey(attr);
+    if (i < 0) {
+        return 0;
+    }
+    mItems.removeItemsAt(i);
+    return 1;
+}
+
+
+// handle individual items/properties stored within the class
+//
+MediaAnalyticsItem::Item::Item()
+        : mType(kTypeNone)
+{
+}
+
+MediaAnalyticsItem::Item::~Item()
+{
+    clear();
+}
+
+void MediaAnalyticsItem::Item::clear()
+{
+    if (mType == kTypeCString && u.CStringValue != NULL) {
+        free(u.CStringValue);
+        u.CStringValue = NULL;
+    }
+    mType = kTypeNone;
+}
+
+// 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::Item::kTypeInt32:
+                            setInt32(attr, data.readInt32());
+                            break;
+                    case MediaAnalyticsItem::Item::kTypeInt64:
+                            setInt64(attr, data.readInt64());
+                            break;
+                    case MediaAnalyticsItem::Item::kTypeDouble:
+                            setDouble(attr, data.readDouble());
+                            break;
+                    case MediaAnalyticsItem::Item::kTypeCString:
+                            setCString(attr, data.readCString());
+                            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 = mItems.size();
+    data->writeInt32(count);
+    for (int i = 0 ; i < count; i++ ) {
+            MediaAnalyticsItem::Attr attr = mItems.keyAt(i);
+            sp<Item> value = mItems.valueAt(i);
+            {
+                data->writeCString(attr.c_str());
+                data->writeInt32(value->mType);
+                switch (value->mType) {
+                    case MediaAnalyticsItem::Item::kTypeInt32:
+                            data->writeInt32(value->u.int32Value);
+                            break;
+                    case MediaAnalyticsItem::Item::kTypeInt64:
+                            data->writeInt64(value->u.int64Value);
+                            break;
+                    case MediaAnalyticsItem::Item::kTypeDouble:
+                            data->writeDouble(value->u.doubleValue);
+                            break;
+                    case MediaAnalyticsItem::Item::kTypeCString:
+                            data->writeCString(value->u.CStringValue);
+                            break;
+                    default:
+                            ALOGE("found bad item type: %d, idx %d",
+                                  value->mType, i);
+                            break;
+                }
+            }
+    }
+
+    return 0;
+}
+
+
+
+AString MediaAnalyticsItem::toString() {
+
+    AString result = "(";
+    char buffer[256];
+
+    // same order as we spill into the parcel, although not required
+    // key+session are our primary matching criteria
+    result.append(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 = mItems.size();
+    snprintf(buffer, sizeof(buffer), "%d:", count);
+    result.append(buffer);
+    for (int i = 0 ; i < count; i++ ) {
+            const MediaAnalyticsItem::Attr attr = mItems.keyAt(i);
+            const sp<Item> value = mItems.valueAt(i);
+            switch (value->mType) {
+                case MediaAnalyticsItem::Item::kTypeInt32:
+                        snprintf(buffer,sizeof(buffer),
+                        "%s=%d:", attr.c_str(), value->u.int32Value);
+                        break;
+                case MediaAnalyticsItem::Item::kTypeInt64:
+                        snprintf(buffer,sizeof(buffer),
+                        "%s=%" PRId64 ":", attr.c_str(), value->u.int64Value);
+                        break;
+                case MediaAnalyticsItem::Item::kTypeDouble:
+                        snprintf(buffer,sizeof(buffer),
+                        "%s=%e:", attr.c_str(), value->u.doubleValue);
+                        break;
+                case MediaAnalyticsItem::Item::kTypeCString:
+                        // XXX: worry about escape chars
+                        // XXX: worry about overflowing buffer
+                        snprintf(buffer,sizeof(buffer), "%s=", attr.c_str());
+                        result.append(buffer);
+                        result.append(value->u.CStringValue);
+                        buffer[0] = ':';
+                        buffer[1] = '\0';
+                        break;
+                default:
+                        ALOGE("to_String bad item type: %d",
+                              value->mType);
+                        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) {
+
+    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 {
+        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.analytics";
+    int enabled = isEnabled();
+
+    if (enabled == false) {
+        if (DEBUG_SERVICEACCESS) {
+                ALOGD("disabled");
+        }
+        return NULL;
+    }
+
+    {
+        Mutex::Autolock _l(sInitMutex);
+        const char *badness = "";
+
+
+        if (sAnalyticsService == NULL) {
+            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";
+            }
+            // always
+            if (1 || DEBUG_SERVICEACCESS) {
+                if (sAnalyticsService == NULL) {
+                    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(sp<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->mItems.size();
+    for (int i = 0 ; i < nattr; i++ ) {
+        const MediaAnalyticsItem::Attr attr = incoming->mItems.keyAt(i);
+        const sp<Item> value = incoming->mItems.valueAt(i);
+
+        const char *p = attr.c_str();
+        char semantic = p[strlen(p)-1];
+
+        switch (semantic) {
+            default:        // default operation is keep new
+            case '>':       // last aka keep new
+                mItems.replaceValueFor(attr, value);
+                break;
+
+            case '<':       /* first aka keep first*/
+                /* nop */
+                break;
+
+            case '+':       /* sum */
+                // XXX validate numeric types, sum in place
+                break;
+
+        }
+    }
+
+    // not sure when we'd return false...
+    return true;
+}
+
+} // namespace android
+
