1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_MEDIA_MEDIAANALYTICSITEM_H
18#define ANDROID_MEDIA_MEDIAANALYTICSITEM_H
19
20#include <cutils/properties.h>
21#include <sys/types.h>
22#include <utils/Errors.h>
23#include <utils/KeyedVector.h>
24#include <utils/RefBase.h>
25#include <utils/StrongPointer.h>
26#include <utils/Timers.h>
27
28#include <media/stagefright/foundation/AString.h>
29
30namespace android {
31
32
33
34class IMediaAnalyticsService;
35
36// the class interface
37//
38
39class MediaAnalyticsItem {
40
41    friend class MediaAnalyticsService;
42    friend class IMediaAnalyticsService;
43    friend class MediaMetricsJNI;
44    friend class MetricsSummarizer;
45    friend class MediaMetricsDeathNotifier;
46
47    public:
48
49            enum Type {
50                kTypeNone = 0,
51                kTypeInt32 = 1,
52                kTypeInt64 = 2,
53                kTypeDouble = 3,
54                kTypeCString = 4,
55                kTypeRate = 5,
56            };
57
58        // sessionid
59        // unique within device, within boot,
60        typedef int64_t SessionID_t;
61        static constexpr SessionID_t SessionIDInvalid = -1;
62        static constexpr SessionID_t SessionIDNone = 0;
63
64        // Key: the record descriminator
65        // values for the record discriminator
66        // values can be "component/component"
67        // basic values: "video", "audio", "drm"
68        // XXX: need to better define the format
69        typedef AString Key;
70        static const Key kKeyNone;              // ""
71        static const Key kKeyAny;               // "*"
72
73        // Attr: names for attributes within a record
74        // format "prop1" or "prop/subprop"
75        // XXX: need to better define the format
76        typedef const char *Attr;
77
78
79        enum {
80            PROTO_V0 = 0,
81            PROTO_FIRST = PROTO_V0,
82            PROTO_V1 = 1,
83            PROTO_LAST = PROTO_V1,
84        };
85
86
87    public:
88
89        // access functions for the class
90        MediaAnalyticsItem();
91        MediaAnalyticsItem(Key);
92        ~MediaAnalyticsItem();
93
94        // so clients can send intermediate values to be overlaid later
95        MediaAnalyticsItem &setFinalized(bool);
96        bool getFinalized() const;
97
98        // SessionID ties multiple submissions for same key together
99        // so that if video "height" and "width" are known at one point
100        // and "framerate" is only known later, they can be be brought
101        // together.
102        MediaAnalyticsItem &setSessionID(SessionID_t);
103        MediaAnalyticsItem &clearSessionID();
104        SessionID_t getSessionID() const;
105        // generates and stores a new ID iff mSessionID == SessionIDNone
106        SessionID_t generateSessionID();
107
108        // reset all contents, discarding any extra data
109        void clear();
110        MediaAnalyticsItem *dup();
111
112        // set the key discriminator for the record.
113        // most often initialized as part of the constructor
114        MediaAnalyticsItem &setKey(MediaAnalyticsItem::Key);
115        MediaAnalyticsItem::Key getKey();
116
117        // # of attributes in the record
118        int32_t count() const;
119
120        // set values appropriately
121        void setInt32(Attr, int32_t value);
122        void setInt64(Attr, int64_t value);
123        void setDouble(Attr, double value);
124        void setRate(Attr, int64_t count, int64_t duration);
125        void setCString(Attr, const char *value);
126
127        // fused get/add/set; if attr wasn't there, it's a simple set.
128        // type-mismatch counts as "wasn't there".
129        void addInt32(Attr, int32_t value);
130        void addInt64(Attr, int64_t value);
131        void addDouble(Attr, double value);
132        void addRate(Attr, int64_t count, int64_t duration);
133
134        // find & extract values
135        // return indicates whether attr exists (and thus value filled in)
136        // NULL parameter value suppresses storage of value.
137        bool getInt32(Attr, int32_t *value);
138        bool getInt64(Attr, int64_t *value);
139        bool getDouble(Attr, double *value);
140        bool getRate(Attr, int64_t *count, int64_t *duration, double *rate);
141        // Caller owns the returned string
142        bool getCString(Attr, char **value);
143
144        // parameter indicates whether to close any existing open
145        // record with same key before establishing a new record
146        // caller retains ownership of 'this'.
147        bool selfrecord(bool);
148        bool selfrecord();
149
150        // remove indicated attributes and their values
151        // filterNot() could also be called keepOnly()
152        // return value is # attributes removed
153        // XXX: perhaps 'remove' instead of 'filter'
154        // XXX: filterNot would become 'keep'
155        int32_t filter(int count, Attr attrs[]);
156        int32_t filterNot(int count, Attr attrs[]);
157        int32_t filter(Attr attr);
158
159        // below here are used on server side or to talk to server
160        // clients need not worry about these.
161
162        // timestamp, pid, and uid only used on server side
163        // timestamp is in 'nanoseconds, unix time'
164        MediaAnalyticsItem &setTimestamp(nsecs_t);
165        nsecs_t getTimestamp() const;
166
167        MediaAnalyticsItem &setPid(pid_t);
168        pid_t getPid() const;
169
170        MediaAnalyticsItem &setUid(uid_t);
171        uid_t getUid() const;
172
173        MediaAnalyticsItem &setPkgName(AString);
174        AString getPkgName() const;
175
176        MediaAnalyticsItem &setPkgVersionCode(int32_t);
177        int32_t getPkgVersionCode() const;
178
179        // our serialization code for binder calls
180        int32_t writeToParcel(Parcel *);
181        int32_t readFromParcel(const Parcel&);
182
183        AString toString();
184        AString toString(int version);
185
186        // are we collecting analytics data
187        static bool isEnabled();
188
189    protected:
190
191        // merge fields from arg into this
192        // with rules for first/last/add, etc
193        // XXX: document semantics and how they are indicated
194        // caller continues to own 'incoming'
195        bool merge(MediaAnalyticsItem *incoming);
196
197        // enabled 1, disabled 0
198        static const char * const EnabledProperty;
199        static const char * const EnabledPropertyPersist;
200        static const int   EnabledProperty_default;
201
202    private:
203
204        // to help validate that A doesn't mess with B's records
205        pid_t     mPid;
206        uid_t     mUid;
207        AString   mPkgName;
208        int32_t   mPkgVersionCode;
209
210        // let's reuse a binder connection
211        static sp<IMediaAnalyticsService> sAnalyticsService;
212        static sp<IMediaAnalyticsService> getInstance();
213        static void dropInstance();
214
215        // tracking information
216        SessionID_t mSessionID;         // grouping similar records
217        nsecs_t mTimestamp;             // ns, system_time_monotonic
218
219        // will this record accept further updates
220        bool mFinalized;
221
222        Key mKey;
223
224        struct Prop {
225
226            Type mType;
227            const char *mName;
228            size_t mNameLen;    // the strlen(), doesn't include the null
229            union {
230                    int32_t int32Value;
231                    int64_t int64Value;
232                    double doubleValue;
233                    char *CStringValue;
234                    struct { int64_t count, duration; } rate;
235            } u;
236            void setName(const char *name, size_t len);
237        };
238
239        void initProp(Prop *item);
240        void clearProp(Prop *item);
241        void clearPropValue(Prop *item);
242        void copyProp(Prop *dst, const Prop *src);
243        enum {
244            kGrowProps = 10
245        };
246        void growProps(int increment = kGrowProps);
247        size_t findPropIndex(const char *name, size_t len);
248        Prop *findProp(const char *name);
249        Prop *allocateProp(const char *name);
250        bool removeProp(const char *name);
251
252        size_t mPropCount;
253        size_t mPropSize;
254        Prop *mProps;
255};
256
257} // namespace android
258
259#endif
260