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