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