13938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick/*
23938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick * Copyright (C) 2016 The Android Open Source Project
33938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick *
43938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick * Licensed under the Apache License, Version 2.0 (the "License");
53938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick * you may not use this file except in compliance with the License.
63938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick * You may obtain a copy of the License at
73938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick *
83938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick *      http://www.apache.org/licenses/LICENSE-2.0
93938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick *
103938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick * Unless required by applicable law or agreed to in writing, software
113938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick * distributed under the License is distributed on an "AS IS" BASIS,
123938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick * See the License for the specific language governing permissions and
143938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick * limitations under the License.
153938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick */
163938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
173938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#undef LOG_TAG
183938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#define LOG_TAG "MediaAnalyticsItem"
193938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
203938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#include <inttypes.h>
21b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick#include <stdlib.h>
22b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick#include <string.h>
23b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick#include <sys/types.h>
243938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
253938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#include <binder/Parcel.h>
263938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#include <utils/Errors.h>
273938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#include <utils/Log.h>
283938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#include <utils/Mutex.h>
293938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#include <utils/SortedVector.h>
303938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#include <utils/threads.h>
313938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
323938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#include <media/stagefright/foundation/AString.h>
333938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
343938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#include <binder/IServiceManager.h>
353938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#include <media/IMediaAnalyticsService.h>
363938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#include <media/MediaAnalyticsItem.h>
3779a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick#include <private/android_filesystem_config.h>
383938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
393938dc6363949ef126bb6188d26b5bef6db8be4dRay Essicknamespace android {
403938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
413938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick#define DEBUG_SERVICEACCESS     0
42b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick#define DEBUG_API               0
43b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick#define DEBUG_ALLOCATIONS       0
44b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
45b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick// after this many failed attempts, we stop trying [from this process] and just say that
46b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick// the service is off.
47b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick#define SVC_TRIES               2
483938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
493938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// the few universal keys we have
503938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickconst MediaAnalyticsItem::Key MediaAnalyticsItem::kKeyAny  = "any";
513938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickconst MediaAnalyticsItem::Key MediaAnalyticsItem::kKeyNone  = "none";
523938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
53d38e174ddbde8e7419ba01deaded4ff0ead1caaaRay Essickconst char * const MediaAnalyticsItem::EnabledProperty  = "media.metrics.enabled";
54d38e174ddbde8e7419ba01deaded4ff0ead1caaaRay Essickconst char * const MediaAnalyticsItem::EnabledPropertyPersist  = "persist.media.metrics.enabled";
55d6a6c677f59c6354157a951cb6ad881600a9f8b8Ray Essickconst int MediaAnalyticsItem::EnabledProperty_default  = 1;
563938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
573938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
583938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// access functions for the class
593938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem::MediaAnalyticsItem()
60d38e174ddbde8e7419ba01deaded4ff0ead1caaaRay Essick    : mPid(-1),
61d38e174ddbde8e7419ba01deaded4ff0ead1caaaRay Essick      mUid(-1),
623938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick      mSessionID(MediaAnalyticsItem::SessionIDNone),
633938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick      mTimestamp(0),
64b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick      mFinalized(0),
65b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick      mPropCount(0), mPropSize(0), mProps(NULL)
66b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick{
673938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mKey = MediaAnalyticsItem::kKeyNone;
683938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
693938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
703938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem::MediaAnalyticsItem(MediaAnalyticsItem::Key key)
71d38e174ddbde8e7419ba01deaded4ff0ead1caaaRay Essick    : mPid(-1),
72d38e174ddbde8e7419ba01deaded4ff0ead1caaaRay Essick      mUid(-1),
733938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick      mSessionID(MediaAnalyticsItem::SessionIDNone),
743938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick      mTimestamp(0),
75b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick      mFinalized(0),
76b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick      mPropCount(0), mPropSize(0), mProps(NULL)
77b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick{
78b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (DEBUG_ALLOCATIONS) {
79b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        ALOGD("Allocate MediaAnalyticsItem @ %p", this);
80b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
813938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mKey = key;
823938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
833938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
843938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem::~MediaAnalyticsItem() {
85b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (DEBUG_ALLOCATIONS) {
86b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        ALOGD("Destroy  MediaAnalyticsItem @ %p", this);
87b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
883938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    clear();
893938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
903938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
91b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::clear() {
92b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
93b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    // clean allocated storage from key
94b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    mKey.clear();
95b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
96d38e174ddbde8e7419ba01deaded4ff0ead1caaaRay Essick    // clean various major parameters
97d38e174ddbde8e7419ba01deaded4ff0ead1caaaRay Essick    mSessionID = MediaAnalyticsItem::SessionIDNone;
98d38e174ddbde8e7419ba01deaded4ff0ead1caaaRay Essick
99b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    // clean attributes
100b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    // contents of the attributes
101b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    for (size_t i = 0 ; i < mPropSize; i++ ) {
102b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        clearProp(&mProps[i]);
103b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
104b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    // the attribute records themselves
105b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (mProps != NULL) {
106b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        free(mProps);
107b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        mProps = NULL;
108b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
109b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    mPropSize = 0;
110b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    mPropCount = 0;
111b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
112b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    return;
113b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
114b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
115b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick// make a deep copy of myself
116b5fac8ef36b302c12f897d06c7e097981843f3a0Ray EssickMediaAnalyticsItem *MediaAnalyticsItem::dup() {
117b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    MediaAnalyticsItem *dst = new MediaAnalyticsItem(this->mKey);
118b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
119b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (dst != NULL) {
120b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        // key as part of constructor
121b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        dst->mPid = this->mPid;
122b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        dst->mUid = this->mUid;
123b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        dst->mSessionID = this->mSessionID;
124b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        dst->mTimestamp = this->mTimestamp;
125b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        dst->mFinalized = this->mFinalized;
126b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
127b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        // properties aka attributes
128b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        dst->growProps(this->mPropCount);
129b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        for(size_t i=0;i<mPropCount;i++) {
130b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            copyProp(&dst->mProps[i], &this->mProps[i]);
131b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        }
132b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        dst->mPropCount = this->mPropCount;
133b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
134b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
135b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    return dst;
136b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
137b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
1383938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// so clients can send intermediate values to be overlaid later
1393938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem &MediaAnalyticsItem::setFinalized(bool value) {
1403938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mFinalized = value;
1413938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return *this;
1423938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
1433938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1443938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickbool MediaAnalyticsItem::getFinalized() const {
1453938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return mFinalized;
1463938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
1473938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1483938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem &MediaAnalyticsItem::setSessionID(MediaAnalyticsItem::SessionID_t id) {
1493938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mSessionID = id;
1503938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return *this;
1513938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
1523938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1533938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem::SessionID_t MediaAnalyticsItem::getSessionID() const {
1543938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return mSessionID;
1553938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
1563938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1573938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem::SessionID_t MediaAnalyticsItem::generateSessionID() {
1583938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1593938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    if (mSessionID == SessionIDNone) {
1603938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        // get one from the server
161b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        MediaAnalyticsItem::SessionID_t newid = SessionIDNone;
1623938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        sp<IMediaAnalyticsService> svc = getInstance();
1633938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        if (svc != NULL) {
1643938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            newid = svc->generateUniqueSessionID();
1653938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        }
1663938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        mSessionID = newid;
1673938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
1683938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1693938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return mSessionID;
1703938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
1713938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1723938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem &MediaAnalyticsItem::clearSessionID() {
1733938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mSessionID = MediaAnalyticsItem::SessionIDNone;
1743938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return *this;
1753938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
1763938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1773938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem &MediaAnalyticsItem::setTimestamp(nsecs_t ts) {
1783938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mTimestamp = ts;
1793938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return *this;
1803938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
1813938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1823938dc6363949ef126bb6188d26b5bef6db8be4dRay Essicknsecs_t MediaAnalyticsItem::getTimestamp() const {
1833938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return mTimestamp;
1843938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
1853938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1863938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem &MediaAnalyticsItem::setPid(pid_t pid) {
1873938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mPid = pid;
1883938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return *this;
1893938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
1903938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1913938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickpid_t MediaAnalyticsItem::getPid() const {
1923938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return mPid;
1933938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
1943938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
1953938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem &MediaAnalyticsItem::setUid(uid_t uid) {
1963938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mUid = uid;
1973938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return *this;
1983938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
1993938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
2003938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickuid_t MediaAnalyticsItem::getUid() const {
2013938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return mUid;
2023938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
2033938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
204b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick// this key is for the overall record -- "codec", "player", "drm", etc
2053938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem &MediaAnalyticsItem::setKey(MediaAnalyticsItem::Key key) {
2063938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mKey = key;
2073938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return *this;
2083938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
2093938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
2103938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickMediaAnalyticsItem::Key MediaAnalyticsItem::getKey() {
2113938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return mKey;
2123938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
2133938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
214b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick// number of attributes we have in this record
2153938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickint32_t MediaAnalyticsItem::count() const {
216b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    return mPropCount;
2173938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
2183938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
219b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick// find the proper entry in the list
220b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essicksize_t MediaAnalyticsItem::findPropIndex(const char *name, size_t len)
221b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick{
222b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    size_t i = 0;
223b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    for (; i < mPropCount; i++) {
224b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        Prop *prop = &mProps[i];
225b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        if (prop->mNameLen != len) {
226b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            continue;
227b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        }
228b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        if (memcmp(name, prop->mName, len) == 0) {
229b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            break;
230b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        }
231b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
232b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    return i;
2333938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
2343938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
235b5fac8ef36b302c12f897d06c7e097981843f3a0Ray EssickMediaAnalyticsItem::Prop *MediaAnalyticsItem::findProp(const char *name) {
236b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    size_t len = strlen(name);
237b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    size_t i = findPropIndex(name, len);
238b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (i < mPropCount) {
239b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        return &mProps[i];
2403938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
241b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    return NULL;
2423938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
2433938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
244b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::Prop::setName(const char *name, size_t len) {
245b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    mNameLen = len;
246b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    mName = (const char *) malloc(len+1);
247b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    memcpy ((void *)mName, name, len+1);
248b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
249b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
250b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick// used only as part of a storing operation
251b5fac8ef36b302c12f897d06c7e097981843f3a0Ray EssickMediaAnalyticsItem::Prop *MediaAnalyticsItem::allocateProp(const char *name) {
252b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    size_t len = strlen(name);
253b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    size_t i = findPropIndex(name, len);
254b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop;
255b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
256b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (i < mPropCount) {
257b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        prop = &mProps[i];
2583938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    } else {
259b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        if (i == mPropSize) {
260b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            growProps();
261b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            // XXX: verify success
262b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        }
263b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        i = mPropCount++;
264b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        prop = &mProps[i];
265b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        prop->setName(name, len);
2663938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
267b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
268b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    return prop;
2693938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
2703938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
271b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick// set the values
272b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::setInt32(MediaAnalyticsItem::Attr name, int32_t value) {
273b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = allocateProp(name);
274b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    prop->mType = kTypeInt32;
275b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    prop->u.int32Value = value;
276b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
277b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
278b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::setInt64(MediaAnalyticsItem::Attr name, int64_t value) {
279b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = allocateProp(name);
280b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    prop->mType = kTypeInt64;
281b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    prop->u.int64Value = value;
282b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
283b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
284b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::setDouble(MediaAnalyticsItem::Attr name, double value) {
285b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = allocateProp(name);
286b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    prop->mType = kTypeDouble;
287b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    prop->u.doubleValue = value;
288b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
289b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
290b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::setCString(MediaAnalyticsItem::Attr name, const char *value) {
291b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
292b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = allocateProp(name);
293b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    // any old value will be gone
294b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    prop->mType = kTypeCString;
295b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    prop->u.CStringValue = strdup(value);
296b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
297b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
298b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::setRate(MediaAnalyticsItem::Attr name, int64_t count, int64_t duration) {
299b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = allocateProp(name);
300b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    prop->mType = kTypeRate;
301b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    prop->u.rate.count = count;
302b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    prop->u.rate.duration = duration;
303b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
304b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
305b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
306b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick// find/add/set fused into a single operation
307b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::addInt32(MediaAnalyticsItem::Attr name, int32_t value) {
308b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = allocateProp(name);
309b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    switch (prop->mType) {
310b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        case kTypeInt32:
311b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->u.int32Value += value;
312b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            break;
313b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        default:
314b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            clearPropValue(prop);
315b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->mType = kTypeInt32;
316b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->u.int32Value = value;
317b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            break;
318b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
319b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
320b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
321b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::addInt64(MediaAnalyticsItem::Attr name, int64_t value) {
322b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = allocateProp(name);
323b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    switch (prop->mType) {
324b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        case kTypeInt64:
325b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->u.int64Value += value;
326b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            break;
327b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        default:
328b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            clearPropValue(prop);
329b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->mType = kTypeInt64;
330b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->u.int64Value = value;
331b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            break;
332b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
333b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
334b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
335b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::addRate(MediaAnalyticsItem::Attr name, int64_t count, int64_t duration) {
336b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = allocateProp(name);
337b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    switch (prop->mType) {
338b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        case kTypeRate:
339b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->u.rate.count += count;
340b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->u.rate.duration += duration;
341b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            break;
342b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        default:
343b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            clearPropValue(prop);
344b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->mType = kTypeRate;
345b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->u.rate.count = count;
346b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->u.rate.duration = duration;
347b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            break;
348b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
349b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
350b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
351b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::addDouble(MediaAnalyticsItem::Attr name, double value) {
352b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = allocateProp(name);
353b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    switch (prop->mType) {
354b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        case kTypeDouble:
355b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->u.doubleValue += value;
356b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            break;
357b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        default:
358b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            clearPropValue(prop);
359b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->mType = kTypeDouble;
360b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->u.doubleValue = value;
361b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            break;
3623938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
3633938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
3643938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
3653938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// find & extract values
366b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickbool MediaAnalyticsItem::getInt32(MediaAnalyticsItem::Attr name, int32_t *value) {
367b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = findProp(name);
368b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (prop == NULL || prop->mType != kTypeInt32) {
369b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        return false;
370b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
371b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (value != NULL) {
372b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        *value = prop->u.int32Value;
373b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
374b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    return true;
375b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
376b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
377b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickbool MediaAnalyticsItem::getInt64(MediaAnalyticsItem::Attr name, int64_t *value) {
378b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = findProp(name);
379b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (prop == NULL || prop->mType != kTypeInt64) {
3803938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        return false;
3813938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
382b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (value != NULL) {
383b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        *value = prop->u.int64Value;
384b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
3853938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return true;
3863938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
387b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
388b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickbool MediaAnalyticsItem::getRate(MediaAnalyticsItem::Attr name, int64_t *count, int64_t *duration, double *rate) {
389b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = findProp(name);
390b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (prop == NULL || prop->mType != kTypeRate) {
3913938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        return false;
3923938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
393b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (count != NULL) {
394b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        *count = prop->u.rate.count;
395b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
396b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (duration != NULL) {
397b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        *duration = prop->u.rate.duration;
398b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
399b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (rate != NULL) {
400b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        double r = 0.0;
401b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        if (prop->u.rate.duration != 0) {
402b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            r = prop->u.rate.count / (double) prop->u.rate.duration;
403b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        }
404b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        *rate = r;
405b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
4063938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return true;
4073938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
408b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
409b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickbool MediaAnalyticsItem::getDouble(MediaAnalyticsItem::Attr name, double *value) {
410b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = findProp(name);
411b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (prop == NULL || prop->mType != kTypeDouble) {
4123938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        return false;
4133938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
414b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (value != NULL) {
415b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        *value = prop->u.doubleValue;
416b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
4173938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return true;
4183938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
4193938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
4203938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// caller responsible for the returned string
421b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickbool MediaAnalyticsItem::getCString(MediaAnalyticsItem::Attr name, char **value) {
422b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *prop = findProp(name);
423b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (prop == NULL || prop->mType != kTypeDouble) {
4243938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        return false;
4253938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
426b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (value != NULL) {
427b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        *value = strdup(prop->u.CStringValue);
428b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
4293938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return true;
4303938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
4313938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
4323938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// remove indicated keys and their values
4333938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// return value is # keys removed
4343938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickint32_t MediaAnalyticsItem::filter(int n, MediaAnalyticsItem::Attr attrs[]) {
4353938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    int zapped = 0;
436b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (attrs == NULL || n <= 0) {
4373938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        return -1;
4383938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
4393938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    for (ssize_t i = 0 ; i < n ;  i++) {
440b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        const char *name = attrs[i];
441b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        size_t len = strlen(name);
442b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        size_t j = findPropIndex(name, len);
443b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        if (j >= mPropCount) {
444b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            // not there
445b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            continue;
446b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        } else if (j+1 == mPropCount) {
447b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            // last one, shorten
4483938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            zapped++;
449b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            clearProp(&mProps[j]);
450b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            mPropCount--;
451b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        } else {
452b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            // in the middle, bring last one down and shorten
453b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            zapped++;
454b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            clearProp(&mProps[j]);
455b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            mProps[j] = mProps[mPropCount-1];
456b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            mPropCount--;
4573938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        }
4583938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
4593938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return zapped;
4603938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
4613938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
4623938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// remove any keys NOT in the provided list
4633938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// return value is # keys removed
4643938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickint32_t MediaAnalyticsItem::filterNot(int n, MediaAnalyticsItem::Attr attrs[]) {
4653938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    int zapped = 0;
466b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (attrs == NULL || n <= 0) {
4673938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        return -1;
4683938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
469b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    for (ssize_t i = mPropCount-1 ; i >=0 ;  i--) {
470b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        Prop *prop = &mProps[i];
471b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        for (ssize_t j = 0; j < n ; j++) {
472b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            if (strcmp(prop->mName, attrs[j]) == 0) {
473b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                clearProp(prop);
4743938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                zapped++;
475b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                if (i != (ssize_t)(mPropCount-1)) {
476b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    *prop = mProps[mPropCount-1];
477b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                }
478b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                initProp(&mProps[mPropCount-1]);
479b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                mPropCount--;
4803938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                break;
4813938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            }
4823938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        }
4833938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
4843938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return zapped;
4853938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
4863938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
4873938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// remove a single key
4883938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// return value is 0 (not found) or 1 (found and removed)
489b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickint32_t MediaAnalyticsItem::filter(MediaAnalyticsItem::Attr name) {
490b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    return filter(1, &name);
4913938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
4923938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
4933938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// handle individual items/properties stored within the class
4943938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick//
495b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
496b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::initProp(Prop *prop) {
497b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (prop != NULL) {
498b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        prop->mName = NULL;
499b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        prop->mNameLen = 0;
500b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
501b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        prop->mType = kTypeNone;
502b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
503b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
504b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
505b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::clearProp(Prop *prop)
5063938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick{
507b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (prop != NULL) {
508b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        if (prop->mName != NULL) {
509b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            free((void *)prop->mName);
510b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->mName = NULL;
511b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->mNameLen = 0;
512b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        }
513b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
514b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        clearPropValue(prop);
515b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
5163938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
5173938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
518b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::clearPropValue(Prop *prop)
5193938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick{
520b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (prop != NULL) {
521b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        if (prop->mType == kTypeCString && prop->u.CStringValue != NULL) {
522b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            free(prop->u.CStringValue);
523b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            prop->u.CStringValue = NULL;
524b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        }
525b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        prop->mType = kTypeNone;
526b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
5273938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
5283938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
529b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::copyProp(Prop *dst, const Prop *src)
5303938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick{
531b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    // get rid of any pointers in the dst
532b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    clearProp(dst);
533b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
534b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    *dst = *src;
535b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
536b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    // fix any pointers that we blindly copied, so we have our own copies
537b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (dst->mName) {
538b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        void *p =  malloc(dst->mNameLen + 1);
539b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        memcpy (p, src->mName, dst->mNameLen + 1);
540b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        dst->mName = (const char *) p;
541b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
542b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (dst->mType == kTypeCString) {
543b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        dst->u.CStringValue = strdup(src->u.CStringValue);
544b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
545b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick}
546b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
547b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickvoid MediaAnalyticsItem::growProps(int increment)
548b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick{
549b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (increment <= 0) {
550b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        increment = kGrowProps;
551b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
552b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    int nsize = mPropSize + increment;
553b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    Prop *ni = (Prop *)realloc(mProps, sizeof(Prop) * nsize);
554b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
555b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (ni != NULL) {
556b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        for (int i = mPropSize; i < nsize; i++) {
557b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            initProp(&ni[i]);
558b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        }
559b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        mProps = ni;
560b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        mPropSize = nsize;
5613938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
5623938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
5633938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
5643938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// Parcel / serialize things for binder calls
5653938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick//
5663938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
5673938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickint32_t MediaAnalyticsItem::readFromParcel(const Parcel& data) {
5683938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // into 'this' object
5693938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // .. we make a copy of the string to put away.
5703938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mKey = data.readCString();
5713938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mSessionID = data.readInt64();
5723938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mFinalized = data.readInt32();
5733938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    mTimestamp = data.readInt64();
5743938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
5753938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    int count = data.readInt32();
5763938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    for (int i = 0; i < count ; i++) {
5773938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            MediaAnalyticsItem::Attr attr = data.readCString();
5783938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            int32_t ztype = data.readInt32();
5793938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                switch (ztype) {
580b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    case MediaAnalyticsItem::kTypeInt32:
5813938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                            setInt32(attr, data.readInt32());
5823938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                            break;
583b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    case MediaAnalyticsItem::kTypeInt64:
5843938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                            setInt64(attr, data.readInt64());
5853938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                            break;
586b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    case MediaAnalyticsItem::kTypeDouble:
5873938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                            setDouble(attr, data.readDouble());
5883938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                            break;
589b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    case MediaAnalyticsItem::kTypeCString:
5903938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                            setCString(attr, data.readCString());
5913938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                            break;
592b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    case MediaAnalyticsItem::kTypeRate:
593b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                            {
594b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                                int64_t count = data.readInt64();
595b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                                int64_t duration = data.readInt64();
596b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                                setRate(attr, count, duration);
597b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                            }
598b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                            break;
5993938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                    default:
6003938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                            ALOGE("reading bad item type: %d, idx %d",
6013938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                                  ztype, i);
6023938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                            return -1;
6033938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                }
6043938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
6053938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6063938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return 0;
6073938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
6083938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6093938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickint32_t MediaAnalyticsItem::writeToParcel(Parcel *data) {
6103938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    if (data == NULL) return -1;
6113938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6123938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6133938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    data->writeCString(mKey.c_str());
6143938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    data->writeInt64(mSessionID);
6153938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    data->writeInt32(mFinalized);
6163938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    data->writeInt64(mTimestamp);
6173938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6183938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // set of items
619b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    int count = mPropCount;
6203938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    data->writeInt32(count);
6213938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    for (int i = 0 ; i < count; i++ ) {
622b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            Prop *prop = &mProps[i];
623b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            data->writeCString(prop->mName);
624b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            data->writeInt32(prop->mType);
625b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            switch (prop->mType) {
626b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case MediaAnalyticsItem::kTypeInt32:
627b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        data->writeInt32(prop->u.int32Value);
628b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        break;
629b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case MediaAnalyticsItem::kTypeInt64:
630b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        data->writeInt64(prop->u.int64Value);
631b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        break;
632b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case MediaAnalyticsItem::kTypeDouble:
633b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        data->writeDouble(prop->u.doubleValue);
634b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        break;
635b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case MediaAnalyticsItem::kTypeRate:
636b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        data->writeInt64(prop->u.rate.count);
637b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        data->writeInt64(prop->u.rate.duration);
638b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        break;
639b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case MediaAnalyticsItem::kTypeCString:
640b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        data->writeCString(prop->u.CStringValue);
641b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        break;
642b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                default:
643b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        ALOGE("found bad Prop type: %d, idx %d, name %s",
644b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                              prop->mType, i, prop->mName);
645b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        break;
6463938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            }
6473938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
6483938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6493938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return 0;
6503938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
6513938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6523938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6533938dc6363949ef126bb6188d26b5bef6db8be4dRay EssickAString MediaAnalyticsItem::toString() {
6543938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6553938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    AString result = "(";
656b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    char buffer[512];
6573938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6583938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // same order as we spill into the parcel, although not required
6593938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // key+session are our primary matching criteria
660b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    //RBE ALOGD("mKey.c_str");
6613938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    result.append(mKey.c_str());
662b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    //RBE ALOGD("post-mKey.c_str");
6633938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    result.append(":");
6643938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    snprintf(buffer, sizeof(buffer), "%" PRId64 ":", mSessionID);
6653938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    result.append(buffer);
6663938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6673938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // we need these internally, but don't want to upload them
6683938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    snprintf(buffer, sizeof(buffer), "%d:%d", mUid, mPid);
6693938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    result.append(buffer);
6703938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6713938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    snprintf(buffer, sizeof(buffer), "%d:", mFinalized);
6723938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    result.append(buffer);
6733938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    snprintf(buffer, sizeof(buffer), "%" PRId64 ":", mTimestamp);
6743938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    result.append(buffer);
6753938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
6763938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // set of items
677b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    int count = mPropCount;
6783938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    snprintf(buffer, sizeof(buffer), "%d:", count);
6793938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    result.append(buffer);
6803938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    for (int i = 0 ; i < count; i++ ) {
681b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            Prop *prop = &mProps[i];
682b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            switch (prop->mType) {
683b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case MediaAnalyticsItem::kTypeInt32:
6843938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                        snprintf(buffer,sizeof(buffer),
685b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        "%s=%d:", prop->mName, prop->u.int32Value);
6863938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                        break;
687b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case MediaAnalyticsItem::kTypeInt64:
6883938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                        snprintf(buffer,sizeof(buffer),
689b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        "%s=%" PRId64 ":", prop->mName, prop->u.int64Value);
6903938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                        break;
691b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case MediaAnalyticsItem::kTypeDouble:
6923938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                        snprintf(buffer,sizeof(buffer),
693b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        "%s=%e:", prop->mName, prop->u.doubleValue);
6943938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                        break;
695b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case MediaAnalyticsItem::kTypeRate:
696b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        snprintf(buffer,sizeof(buffer),
697b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        "%s=%" PRId64 "/%" PRId64 ":", prop->mName,
698b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        prop->u.rate.count, prop->u.rate.duration);
699b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        break;
700b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case MediaAnalyticsItem::kTypeCString:
701b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        snprintf(buffer,sizeof(buffer), "%s=", prop->mName);
7023938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                        result.append(buffer);
703b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        // XXX: sanitize string for ':' '='
704b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        result.append(prop->u.CStringValue);
7053938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                        buffer[0] = ':';
7063938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                        buffer[1] = '\0';
7073938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                        break;
7083938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                default:
709b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                        ALOGE("to_String bad item type: %d for %s",
710b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                              prop->mType, prop->mName);
7113938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                        break;
7123938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            }
7133938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            result.append(buffer);
7143938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
7153938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
7163938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    result.append(")");
7173938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
7183938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return result;
7193938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
7203938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
7213938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// for the lazy, we offer methods that finds the service and
7223938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// calls the appropriate daemon
7233938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickbool MediaAnalyticsItem::selfrecord() {
7243938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return selfrecord(false);
7253938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
7263938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
7273938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickbool MediaAnalyticsItem::selfrecord(bool forcenew) {
7283938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
729b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    if (DEBUG_API) {
730b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        AString p = this->toString();
731b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        ALOGD("selfrecord of: %s [forcenew=%d]", p.c_str(), forcenew);
732b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    }
7333938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
7343938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    sp<IMediaAnalyticsService> svc = getInstance();
7353938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
7363938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    if (svc != NULL) {
7373938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        svc->submit(this, forcenew);
7383938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        return true;
7393938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    } else {
740b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        AString p = this->toString();
741b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        ALOGD("Unable to record: %s [forcenew=%d]", p.c_str(), forcenew);
7423938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        return false;
7433938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
7443938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
7453938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
7463938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// get a connection we can reuse for most of our lifetime
7473938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// static
7483938dc6363949ef126bb6188d26b5bef6db8be4dRay Essicksp<IMediaAnalyticsService> MediaAnalyticsItem::sAnalyticsService;
7493938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickstatic Mutex sInitMutex;
7503938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
7513938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick//static
7523938dc6363949ef126bb6188d26b5bef6db8be4dRay Essickbool MediaAnalyticsItem::isEnabled() {
7533938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    int enabled = property_get_int32(MediaAnalyticsItem::EnabledProperty, -1);
7543938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
7553938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    if (enabled == -1) {
7563938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        enabled = property_get_int32(MediaAnalyticsItem::EnabledPropertyPersist, -1);
7573938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
7583938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    if (enabled == -1) {
7593938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        enabled = MediaAnalyticsItem::EnabledProperty_default;
7603938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
7613938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    if (enabled <= 0) {
7623938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        return false;
7633938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
7643938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return true;
7653938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
7663938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
7673938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick//static
7683938dc6363949ef126bb6188d26b5bef6db8be4dRay Essicksp<IMediaAnalyticsService> MediaAnalyticsItem::getInstance() {
769d38e174ddbde8e7419ba01deaded4ff0ead1caaaRay Essick    static const char *servicename = "media.metrics";
770b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    static int tries_remaining = SVC_TRIES;
7713938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    int enabled = isEnabled();
7723938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
7733938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    if (enabled == false) {
7743938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        if (DEBUG_SERVICEACCESS) {
7753938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                ALOGD("disabled");
7763938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        }
7773938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        return NULL;
7783938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
7793938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
78079a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick    // completely skip logging from certain UIDs. We do this here
78179a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick    // to avoid the multi-second timeouts while we learn that
78279a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick    // sepolicy will not let us find the service.
78379a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick    // We do this only for a select set of UIDs
78479a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick    // The sepolicy protection is still in place, we just want a faster
78579a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick    // response from this specific, small set of uids.
78679a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick    {
78779a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick        uid_t uid = getuid();
78879a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick        switch (uid) {
78979a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick            case AID_RADIO:     // telephony subsystem, RIL
79079a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick                return NULL;
79179a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick                break;
79279a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick            default:
79379a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick                // let sepolicy deny access if appropriate
79479a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick                break;
79579a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick        }
79679a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick    }
79779a89ef4eb06a2d29fc3d083112de398111a9ddbRay Essick
7983938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    {
7993938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        Mutex::Autolock _l(sInitMutex);
8003938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        const char *badness = "";
8013938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
802b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        // think of tries_remaining as telling us whether service==NULL because
803b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        // (1) we haven't tried to initialize it yet
804b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        // (2) we've tried to initialize it, but failed.
805b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        if (sAnalyticsService == NULL && tries_remaining > 0) {
8063938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            sp<IServiceManager> sm = defaultServiceManager();
8073938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            if (sm != NULL) {
8083938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                sp<IBinder> binder = sm->getService(String16(servicename));
8093938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                if (binder != NULL) {
8103938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                    sAnalyticsService = interface_cast<IMediaAnalyticsService>(binder);
8113938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                } else {
8123938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                    badness = "did not find service";
8133938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                }
8143938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            } else {
8153938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                badness = "No Service Manager access";
8163938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            }
817b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
818b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            if (sAnalyticsService == NULL) {
819b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                if (tries_remaining > 0) {
820b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    tries_remaining--;
821b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                }
822b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                if (DEBUG_SERVICEACCESS) {
8233938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                    ALOGD("Unable to bind to service %s: %s", servicename, badness);
8243938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick                }
8253938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick            }
8263938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        }
827b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
8283938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        return sAnalyticsService;
8293938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
8303938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
8313938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
8323938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
8333938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// merge the info from 'incoming' into this record.
8343938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick// we finish with a union of this+incoming and special handling for collisions
835b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essickbool MediaAnalyticsItem::merge(MediaAnalyticsItem *incoming) {
8363938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
8373938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // if I don't have key or session id, take them from incoming
8383938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // 'this' should never be missing both of them...
8393938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    if (mKey.empty()) {
8403938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        mKey = incoming->mKey;
8413938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    } else if (mSessionID == 0) {
8423938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        mSessionID = incoming->mSessionID;
8433938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
8443938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
8453938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // we always take the more recent 'finalized' value
8463938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    setFinalized(incoming->getFinalized());
8473938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
8483938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // for each attribute from 'incoming', resolve appropriately
849b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick    int nattr = incoming->mPropCount;
8503938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    for (int i = 0 ; i < nattr; i++ ) {
851b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        Prop *iprop = &incoming->mProps[i];
852b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        Prop *oprop = findProp(iprop->mName);
853b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        const char *p = iprop->mName;
854b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        size_t len = strlen(p);
855b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        char semantic = p[len-1];
856b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
857b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        if (oprop == NULL) {
858b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            // no oprop, so we insert the new one
859b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            oprop = allocateProp(p);
860b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            copyProp(oprop, iprop);
861b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick        } else {
862b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            // merge iprop into oprop
863b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            switch (semantic) {
864b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case '<':       // first  aka keep old)
865b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    /* nop */
866b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    break;
867b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
868b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                default:        // default is 'last'
869b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case '>':       // last (aka keep new)
870b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    copyProp(oprop, iprop);
871b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    break;
872b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick
873b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                case '+':       /* sum */
874b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    // XXX validate numeric types, sum in place
875b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick                    break;
8763938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
877b5fac8ef36b302c12f897d06c7e097981843f3a0Ray Essick            }
8783938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick        }
8793938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    }
8803938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
8813938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    // not sure when we'd return false...
8823938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick    return true;
8833938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick}
8843938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
8853938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick} // namespace android
8863938dc6363949ef126bb6188d26b5bef6db8be4dRay Essick
887