1 /*
2 * Copyright (C) 2018 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 #define DEBUG false
18 #include "Log.h"
19 #include "FieldValue.h"
20 #include "HashableDimensionKey.h"
21 #include "math.h"
22 #include "statslog.h"
23
24 namespace android {
25 namespace os {
26 namespace statsd {
27
getEncodedField(int32_t pos[],int32_t depth,bool includeDepth)28 int32_t getEncodedField(int32_t pos[], int32_t depth, bool includeDepth) {
29 int32_t field = 0;
30 for (int32_t i = 0; i <= depth; i++) {
31 int32_t shiftBits = 8 * (kMaxLogDepth - i);
32 field |= (pos[i] << shiftBits);
33 }
34
35 if (includeDepth) {
36 field |= (depth << 24);
37 }
38 return field;
39 }
40
encodeMatcherMask(int32_t mask[],int32_t depth)41 int32_t encodeMatcherMask(int32_t mask[], int32_t depth) {
42 return getEncodedField(mask, depth, false) | 0xff000000;
43 }
44
matches(const Matcher & matcher) const45 bool Field::matches(const Matcher& matcher) const {
46 if (mTag != matcher.mMatcher.getTag()) {
47 return false;
48 }
49 if ((mField & matcher.mMask) == matcher.mMatcher.getField()) {
50 return true;
51 }
52
53 if (matcher.hasAllPositionMatcher() &&
54 (mField & (matcher.mMask & kClearAllPositionMatcherMask)) == matcher.mMatcher.getField()) {
55 return true;
56 }
57
58 return false;
59 }
60
translateFieldMatcher(int tag,const FieldMatcher & matcher,int depth,int * pos,int * mask,std::vector<Matcher> * output)61 void translateFieldMatcher(int tag, const FieldMatcher& matcher, int depth, int* pos, int* mask,
62 std::vector<Matcher>* output) {
63 if (depth > kMaxLogDepth) {
64 ALOGE("depth > 2");
65 return;
66 }
67
68 pos[depth] = matcher.field();
69 mask[depth] = 0x7f;
70
71 if (matcher.has_position()) {
72 depth++;
73 if (depth > 2) {
74 return;
75 }
76 switch (matcher.position()) {
77 case Position::ALL:
78 pos[depth] = 0x00;
79 mask[depth] = 0x7f;
80 break;
81 case Position::ANY:
82 pos[depth] = 0;
83 mask[depth] = 0;
84 break;
85 case Position::FIRST:
86 pos[depth] = 1;
87 mask[depth] = 0x7f;
88 break;
89 case Position::LAST:
90 pos[depth] = 0x80;
91 mask[depth] = 0x80;
92 break;
93 case Position::POSITION_UNKNOWN:
94 pos[depth] = 0;
95 mask[depth] = 0;
96 break;
97 }
98 }
99
100 if (matcher.child_size() == 0) {
101 output->push_back(Matcher(Field(tag, pos, depth), encodeMatcherMask(mask, depth)));
102 } else {
103 for (const auto& child : matcher.child()) {
104 translateFieldMatcher(tag, child, depth + 1, pos, mask, output);
105 }
106 }
107 }
108
translateFieldMatcher(const FieldMatcher & matcher,std::vector<Matcher> * output)109 void translateFieldMatcher(const FieldMatcher& matcher, std::vector<Matcher>* output) {
110 int pos[] = {1, 1, 1};
111 int mask[] = {0x7f, 0x7f, 0x7f};
112 int tag = matcher.field();
113 for (const auto& child : matcher.child()) {
114 translateFieldMatcher(tag, child, 0, pos, mask, output);
115 }
116 }
117
isAttributionUidField(const FieldValue & value)118 bool isAttributionUidField(const FieldValue& value) {
119 int field = value.mField.getField() & 0xff007f;
120 if (field == 0x10001 && value.mValue.getType() == INT) {
121 return true;
122 }
123 return false;
124 }
125
getUidIfExists(const FieldValue & value)126 int32_t getUidIfExists(const FieldValue& value) {
127 bool isUid = false;
128 // the field is uid field if the field is the uid field in attribution node or marked as
129 // is_uid in atoms.proto
130 if (isAttributionUidField(value)) {
131 isUid = true;
132 } else {
133 auto it = android::util::AtomsInfo::kAtomsWithUidField.find(value.mField.getTag());
134 if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) {
135 int uidField = it->second; // uidField is the field number in proto
136 isUid = value.mField.getDepth() == 0 && value.mField.getPosAtDepth(0) == uidField &&
137 value.mValue.getType() == INT;
138 }
139 }
140
141 return isUid ? value.mValue.int_value : -1;
142 }
143
isAttributionUidField(const Field & field,const Value & value)144 bool isAttributionUidField(const Field& field, const Value& value) {
145 int f = field.getField() & 0xff007f;
146 if (f == 0x10001 && value.getType() == INT) {
147 return true;
148 }
149 return false;
150 }
151
Value(const Value & from)152 Value::Value(const Value& from) {
153 type = from.getType();
154 switch (type) {
155 case INT:
156 int_value = from.int_value;
157 break;
158 case LONG:
159 long_value = from.long_value;
160 break;
161 case FLOAT:
162 float_value = from.float_value;
163 break;
164 case DOUBLE:
165 double_value = from.double_value;
166 break;
167 case STRING:
168 str_value = from.str_value;
169 break;
170 case STORAGE:
171 storage_value = from.storage_value;
172 break;
173 default:
174 break;
175 }
176 }
177
toString() const178 std::string Value::toString() const {
179 switch (type) {
180 case INT:
181 return std::to_string(int_value) + "[I]";
182 case LONG:
183 return std::to_string(long_value) + "[L]";
184 case FLOAT:
185 return std::to_string(float_value) + "[F]";
186 case DOUBLE:
187 return std::to_string(double_value) + "[D]";
188 case STRING:
189 return str_value + "[S]";
190 case STORAGE:
191 return "bytes of size " + std::to_string(storage_value.size()) + "[ST]";
192 default:
193 return "[UNKNOWN]";
194 }
195 }
196
isZero() const197 bool Value::isZero() const {
198 switch (type) {
199 case INT:
200 return int_value == 0;
201 case LONG:
202 return long_value == 0;
203 case FLOAT:
204 return fabs(float_value) <= std::numeric_limits<float>::epsilon();
205 case DOUBLE:
206 return fabs(double_value) <= std::numeric_limits<double>::epsilon();
207 case STRING:
208 return str_value.size() == 0;
209 case STORAGE:
210 return storage_value.size() == 0;
211 default:
212 return false;
213 }
214 }
215
operator ==(const Value & that) const216 bool Value::operator==(const Value& that) const {
217 if (type != that.getType()) return false;
218
219 switch (type) {
220 case INT:
221 return int_value == that.int_value;
222 case LONG:
223 return long_value == that.long_value;
224 case FLOAT:
225 return float_value == that.float_value;
226 case DOUBLE:
227 return double_value == that.double_value;
228 case STRING:
229 return str_value == that.str_value;
230 case STORAGE:
231 return storage_value == that.storage_value;
232 default:
233 return false;
234 }
235 }
236
operator !=(const Value & that) const237 bool Value::operator!=(const Value& that) const {
238 if (type != that.getType()) return true;
239 switch (type) {
240 case INT:
241 return int_value != that.int_value;
242 case LONG:
243 return long_value != that.long_value;
244 case FLOAT:
245 return float_value != that.float_value;
246 case DOUBLE:
247 return double_value != that.double_value;
248 case STRING:
249 return str_value != that.str_value;
250 case STORAGE:
251 return storage_value != that.storage_value;
252 default:
253 return false;
254 }
255 }
256
operator <(const Value & that) const257 bool Value::operator<(const Value& that) const {
258 if (type != that.getType()) return type < that.getType();
259
260 switch (type) {
261 case INT:
262 return int_value < that.int_value;
263 case LONG:
264 return long_value < that.long_value;
265 case FLOAT:
266 return float_value < that.float_value;
267 case DOUBLE:
268 return double_value < that.double_value;
269 case STRING:
270 return str_value < that.str_value;
271 case STORAGE:
272 return storage_value < that.storage_value;
273 default:
274 return false;
275 }
276 }
277
operator >(const Value & that) const278 bool Value::operator>(const Value& that) const {
279 if (type != that.getType()) return type > that.getType();
280
281 switch (type) {
282 case INT:
283 return int_value > that.int_value;
284 case LONG:
285 return long_value > that.long_value;
286 case FLOAT:
287 return float_value > that.float_value;
288 case DOUBLE:
289 return double_value > that.double_value;
290 case STRING:
291 return str_value > that.str_value;
292 case STORAGE:
293 return storage_value > that.storage_value;
294 default:
295 return false;
296 }
297 }
298
operator >=(const Value & that) const299 bool Value::operator>=(const Value& that) const {
300 if (type != that.getType()) return type >= that.getType();
301
302 switch (type) {
303 case INT:
304 return int_value >= that.int_value;
305 case LONG:
306 return long_value >= that.long_value;
307 case FLOAT:
308 return float_value >= that.float_value;
309 case DOUBLE:
310 return double_value >= that.double_value;
311 case STRING:
312 return str_value >= that.str_value;
313 case STORAGE:
314 return storage_value >= that.storage_value;
315 default:
316 return false;
317 }
318 }
319
operator -(const Value & that) const320 Value Value::operator-(const Value& that) const {
321 Value v;
322 if (type != that.type) {
323 ALOGE("Can't operate on different value types, %d, %d", type, that.type);
324 return v;
325 }
326 if (type == STRING) {
327 ALOGE("Can't operate on string value type");
328 return v;
329 }
330
331 if (type == STORAGE) {
332 ALOGE("Can't operate on storage value type");
333 return v;
334 }
335
336 switch (type) {
337 case INT:
338 v.setInt(int_value - that.int_value);
339 break;
340 case LONG:
341 v.setLong(long_value - that.long_value);
342 break;
343 case FLOAT:
344 v.setFloat(float_value - that.float_value);
345 break;
346 case DOUBLE:
347 v.setDouble(double_value - that.double_value);
348 break;
349 default:
350 break;
351 }
352 return v;
353 }
354
operator =(const Value & that)355 Value& Value::operator=(const Value& that) {
356 type = that.type;
357 switch (type) {
358 case INT:
359 int_value = that.int_value;
360 break;
361 case LONG:
362 long_value = that.long_value;
363 break;
364 case FLOAT:
365 float_value = that.float_value;
366 break;
367 case DOUBLE:
368 double_value = that.double_value;
369 break;
370 case STRING:
371 str_value = that.str_value;
372 break;
373 case STORAGE:
374 storage_value = that.storage_value;
375 break;
376 default:
377 break;
378 }
379 return *this;
380 }
381
operator +=(const Value & that)382 Value& Value::operator+=(const Value& that) {
383 if (type != that.type) {
384 ALOGE("Can't operate on different value types, %d, %d", type, that.type);
385 return *this;
386 }
387 if (type == STRING) {
388 ALOGE("Can't operate on string value type");
389 return *this;
390 }
391 if (type == STORAGE) {
392 ALOGE("Can't operate on storage value type");
393 return *this;
394 }
395
396 switch (type) {
397 case INT:
398 int_value += that.int_value;
399 break;
400 case LONG:
401 long_value += that.long_value;
402 break;
403 case FLOAT:
404 float_value += that.float_value;
405 break;
406 case DOUBLE:
407 double_value += that.double_value;
408 break;
409 default:
410 break;
411 }
412 return *this;
413 }
414
getDouble() const415 double Value::getDouble() const {
416 switch (type) {
417 case INT:
418 return int_value;
419 case LONG:
420 return long_value;
421 case FLOAT:
422 return float_value;
423 case DOUBLE:
424 return double_value;
425 default:
426 return 0;
427 }
428 }
429
equalDimensions(const std::vector<Matcher> & dimension_a,const std::vector<Matcher> & dimension_b)430 bool equalDimensions(const std::vector<Matcher>& dimension_a,
431 const std::vector<Matcher>& dimension_b) {
432 bool eq = dimension_a.size() == dimension_b.size();
433 for (size_t i = 0; eq && i < dimension_a.size(); ++i) {
434 if (dimension_b[i] != dimension_a[i]) {
435 eq = false;
436 }
437 }
438 return eq;
439 }
440
HasPositionANY(const FieldMatcher & matcher)441 bool HasPositionANY(const FieldMatcher& matcher) {
442 if (matcher.has_position() && matcher.position() == Position::ANY) {
443 return true;
444 }
445 for (const auto& child : matcher.child()) {
446 if (HasPositionANY(child)) {
447 return true;
448 }
449 }
450 return false;
451 }
452
HasPositionALL(const FieldMatcher & matcher)453 bool HasPositionALL(const FieldMatcher& matcher) {
454 if (matcher.has_position() && matcher.position() == Position::ALL) {
455 return true;
456 }
457 for (const auto& child : matcher.child()) {
458 if (HasPositionALL(child)) {
459 return true;
460 }
461 }
462 return false;
463 }
464
465 } // namespace statsd
466 } // namespace os
467 } // namespace android