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