blob: 09499b6406e7721eb81980fce75bc1630bb68372 [file] [log] [blame]
Yangster-mac20877162017-12-22 17:19:39 -08001/*
2 * Copyright (C) 2017 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#include "Log.h"
18
19#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
Yangster-macd19bcae42018-01-04 15:43:39 -080020#include "frameworks/base/cmds/statsd/src/statsd_internal.pb.h"
Yangster-mac20877162017-12-22 17:19:39 -080021#include "dimension.h"
Yangster-mac20877162017-12-22 17:19:39 -080022
23
24namespace android {
25namespace os {
26namespace statsd {
27
28const DimensionsValue* getSingleLeafValue(const DimensionsValue* value) {
29 if (value->value_case() == DimensionsValue::ValueCase::kValueTuple) {
30 return getSingleLeafValue(&value->value_tuple().dimensions_value(0));
31 } else {
32 return value;
33 }
34}
35
36DimensionsValue getSingleLeafValue(const DimensionsValue& value) {
37 const DimensionsValue* leafValue = getSingleLeafValue(&value);
38 return *leafValue;
39}
40
41void appendLeafNodeToParent(const Field& field,
42 const DimensionsValue& value,
43 DimensionsValue* parentValue) {
44 if (field.child_size() <= 0) {
45 *parentValue = value;
46 parentValue->set_field(field.field());
47 return;
48 }
49 parentValue->set_field(field.field());
50 int idx = -1;
51 for (int i = 0; i < parentValue->mutable_value_tuple()->dimensions_value_size(); ++i) {
52 if (parentValue->mutable_value_tuple()->dimensions_value(i).field() ==
53 field.child(0).field()) {
54 idx = i;
55 }
56 }
57 if (idx < 0) {
58 parentValue->mutable_value_tuple()->add_dimensions_value();
59 idx = parentValue->mutable_value_tuple()->dimensions_value_size() - 1;
60 }
61 appendLeafNodeToParent(
62 field.child(0), value,
63 parentValue->mutable_value_tuple()->mutable_dimensions_value(idx));
64}
65
66void addNodeToRootDimensionsValues(const Field& field,
67 const DimensionsValue& node,
68 std::vector<DimensionsValue>* rootValues) {
69 if (rootValues == nullptr) {
70 return;
71 }
72 if (rootValues->empty()) {
73 DimensionsValue rootValue;
74 appendLeafNodeToParent(field, node, &rootValue);
75 rootValues->push_back(rootValue);
76 } else {
77 for (size_t i = 0; i < rootValues->size(); ++i) {
78 appendLeafNodeToParent(field, node, &rootValues->at(i));
79 }
80 }
81}
82
83namespace {
84
85void findDimensionsValues(
86 const FieldValueMap& fieldValueMap,
87 const FieldMatcher& matcher,
88 const Field& field,
89 std::vector<DimensionsValue>* rootDimensionsValues);
90
91void findNonRepeatedDimensionsValues(
92 const FieldValueMap& fieldValueMap,
93 const FieldMatcher& matcher,
94 const Field& field,
95 std::vector<DimensionsValue>* rootValues) {
96 if (matcher.child_size() > 0) {
97 for (const auto& childMatcher : matcher.child()) {
98 Field childField = field;
99 appendLeaf(&childField, childMatcher.field());
100 findDimensionsValues(fieldValueMap, childMatcher, childField, rootValues);
101 }
102 } else {
103 auto ret = fieldValueMap.equal_range(field);
104 int found = 0;
105 for (auto it = ret.first; it != ret.second; ++it) {
106 found++;
107 }
108 // Not found.
109 if (found <= 0) {
110 return;
111 }
112 if (found > 1) {
113 ALOGE("Found multiple values for optional field.");
114 return;
115 }
116 addNodeToRootDimensionsValues(field, ret.first->second, rootValues);
117 }
118}
119
120void findRepeatedDimensionsValues(const FieldValueMap& fieldValueMap,
121 const FieldMatcher& matcher,
122 const Field& field,
123 std::vector<DimensionsValue>* rootValues) {
124 if (matcher.position() == Position::FIRST) {
125 Field first_field = field;
126 setPositionForLeaf(&first_field, 0);
127 findNonRepeatedDimensionsValues(fieldValueMap, matcher, first_field, rootValues);
128 } else {
129 auto itLower = fieldValueMap.lower_bound(field);
130 if (itLower == fieldValueMap.end()) {
131 return;
132 }
133 Field next_field = field;
134 getNextField(&next_field);
135 auto itUpper = fieldValueMap.lower_bound(next_field);
136
137 switch (matcher.position()) {
138 case Position::LAST:
139 {
140 itUpper--;
141 if (itUpper != fieldValueMap.end()) {
142 Field last_field = field;
143 int last_index = getPositionByReferenceField(field, itUpper->first);
144 if (last_index < 0) {
145 return;
146 }
147 setPositionForLeaf(&last_field, last_index);
148 findNonRepeatedDimensionsValues(
149 fieldValueMap, matcher, last_field, rootValues);
150 }
151 }
152 break;
153 case Position::ANY:
154 {
155 std::set<int> indexes;
156 for (auto it = itLower; it != itUpper; ++it) {
157 int index = getPositionByReferenceField(field, it->first);
158 if (index >= 0) {
159 indexes.insert(index);
160 }
161 }
162 if (!indexes.empty()) {
163 Field any_field = field;
164 std::vector<DimensionsValue> allValues;
165 for (const int index : indexes) {
166 setPositionForLeaf(&any_field, index);
167 std::vector<DimensionsValue> newValues = *rootValues;
168 findNonRepeatedDimensionsValues(
169 fieldValueMap, matcher, any_field, &newValues);
170 allValues.insert(allValues.end(), newValues.begin(), newValues.end());
171 }
172 rootValues->clear();
173 rootValues->insert(rootValues->end(), allValues.begin(), allValues.end());
174 }
175 }
176 break;
177 default:
178 break;
179 }
180 }
181}
182
183void findDimensionsValues(
184 const FieldValueMap& fieldValueMap,
185 const FieldMatcher& matcher,
186 const Field& field,
187 std::vector<DimensionsValue>* rootDimensionsValues) {
188 if (!matcher.has_position()) {
189 findNonRepeatedDimensionsValues(fieldValueMap, matcher, field, rootDimensionsValues);
190 } else {
191 findRepeatedDimensionsValues(fieldValueMap, matcher, field, rootDimensionsValues);
192 }
193}
194
195} // namespace
196
197void findDimensionsValues(
198 const FieldValueMap& fieldValueMap,
199 const FieldMatcher& matcher,
200 std::vector<DimensionsValue>* rootDimensionsValues) {
201 findDimensionsValues(fieldValueMap, matcher,
202 buildSimpleAtomField(matcher.field()), rootDimensionsValues);
203}
204
205FieldMatcher buildSimpleAtomFieldMatcher(const int tagId) {
206 FieldMatcher matcher;
207 matcher.set_field(tagId);
208 return matcher;
209}
210
211FieldMatcher buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum) {
212 FieldMatcher matcher;
213 matcher.set_field(tagId);
214 matcher.add_child()->set_field(atomFieldNum);
215 return matcher;
216}
217
218constexpr int ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO = 1;
219constexpr int UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 1;
220constexpr int TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 2;
221
Yangster-macd40053e2018-01-09 16:29:22 -0800222FieldMatcher buildAttributionUidFieldMatcher(const int tagId, const Position position) {
223 FieldMatcher matcher;
224 matcher.set_field(tagId);
225 auto child = matcher.add_child();
Yangster-mac20877162017-12-22 17:19:39 -0800226 child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
227 child->set_position(position);
Yangster-macd40053e2018-01-09 16:29:22 -0800228 child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
229 return matcher;
Yangster-mac20877162017-12-22 17:19:39 -0800230}
231
Yangster-macd40053e2018-01-09 16:29:22 -0800232FieldMatcher buildAttributionTagFieldMatcher(const int tagId, const Position position) {
233 FieldMatcher matcher;
234 matcher.set_field(tagId);
235 FieldMatcher* child = matcher.add_child();
Yangster-mac20877162017-12-22 17:19:39 -0800236 child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
237 child->set_position(position);
Yangster-macd40053e2018-01-09 16:29:22 -0800238 child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
239 return matcher;
240}
241
242FieldMatcher buildAttributionFieldMatcher(const int tagId, const Position position) {
243 FieldMatcher matcher;
244 matcher.set_field(tagId);
245 FieldMatcher* child = matcher.add_child();
246 child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
247 child->set_position(position);
248 child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
249 child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
250 return matcher;
Yangster-mac20877162017-12-22 17:19:39 -0800251}
252
253void DimensionsValueToString(const DimensionsValue& value, std::string *flattened) {
254 *flattened += std::to_string(value.field());
255 *flattened += ":";
256 switch (value.value_case()) {
257 case DimensionsValue::ValueCase::kValueStr:
258 *flattened += value.value_str();
259 break;
260 case DimensionsValue::ValueCase::kValueInt:
261 *flattened += std::to_string(value.value_int());
262 break;
263 case DimensionsValue::ValueCase::kValueLong:
264 *flattened += std::to_string(value.value_long());
265 break;
266 case DimensionsValue::ValueCase::kValueBool:
267 *flattened += std::to_string(value.value_bool());
268 break;
269 case DimensionsValue::ValueCase::kValueFloat:
270 *flattened += std::to_string(value.value_float());
271 break;
272 case DimensionsValue::ValueCase::kValueTuple:
273 {
274 *flattened += "{";
275 for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) {
276 DimensionsValueToString(value.value_tuple().dimensions_value(i), flattened);
277 *flattened += "|";
278 }
279 *flattened += "}";
280 }
281 break;
282 case DimensionsValue::ValueCase::VALUE_NOT_SET:
283 break;
284 }
285}
286
287void getDimensionsValueLeafNodes(
288 const DimensionsValue& value, std::vector<DimensionsValue> *leafNodes) {
289 switch (value.value_case()) {
290 case DimensionsValue::ValueCase::kValueStr:
291 case DimensionsValue::ValueCase::kValueInt:
292 case DimensionsValue::ValueCase::kValueLong:
293 case DimensionsValue::ValueCase::kValueBool:
294 case DimensionsValue::ValueCase::kValueFloat:
295 leafNodes->push_back(value);
296 break;
297 case DimensionsValue::ValueCase::kValueTuple:
298 for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) {
299 getDimensionsValueLeafNodes(value.value_tuple().dimensions_value(i), leafNodes);
300 }
301 break;
302 case DimensionsValue::ValueCase::VALUE_NOT_SET:
303 break;
304 default:
305 break;
306 }
307}
308
309std::string DimensionsValueToString(const DimensionsValue& value) {
310 std::string flatten;
311 DimensionsValueToString(value, &flatten);
312 return flatten;
313}
314
315bool IsSubDimension(const DimensionsValue& dimension, const DimensionsValue& sub) {
316 if (dimension.field() != sub.field()) {
317 return false;
318 }
319 if (dimension.value_case() != sub.value_case()) {
320 return false;
321 }
322 switch (dimension.value_case()) {
323 case DimensionsValue::ValueCase::kValueStr:
324 return dimension.value_str() == sub.value_str();
325 case DimensionsValue::ValueCase::kValueInt:
326 return dimension.value_int() == sub.value_int();
327 case DimensionsValue::ValueCase::kValueLong:
328 return dimension.value_long() == sub.value_long();
329 case DimensionsValue::ValueCase::kValueBool:
330 return dimension.value_bool() == sub.value_bool();
331 case DimensionsValue::ValueCase::kValueFloat:
332 return dimension.value_float() == sub.value_float();
333 case DimensionsValue::ValueCase::kValueTuple: {
334 if (dimension.value_tuple().dimensions_value_size() < sub.value_tuple().dimensions_value_size()) {
335 return false;
336 }
337 bool allSub = true;
338 for (int i = 0; i < sub.value_tuple().dimensions_value_size(); ++i) {
339 bool isSub = false;
340 for (int j = 0; !isSub && j < dimension.value_tuple().dimensions_value_size(); ++j) {
341 isSub |= IsSubDimension(dimension.value_tuple().dimensions_value(j),
342 sub.value_tuple().dimensions_value(i));
343 }
344 allSub &= isSub;
345 }
346 return allSub;
347 }
348 break;
349 case DimensionsValue::ValueCase::VALUE_NOT_SET:
350 return false;
351 default:
352 return false;
353 }
354}
355
Yangster-maca7fb12d2018-01-03 17:17:20 -0800356long getLongFromDimenValue(const DimensionsValue& dimensionValue) {
357 switch (dimensionValue.value_case()) {
358 case DimensionsValue::ValueCase::kValueInt:
359 return dimensionValue.value_int();
360 case DimensionsValue::ValueCase::kValueLong:
361 return dimensionValue.value_long();
362 case DimensionsValue::ValueCase::kValueBool:
363 return dimensionValue.value_bool() ? 1 : 0;
364 case DimensionsValue::ValueCase::kValueFloat:
365 return (int64_t)dimensionValue.value_float();
366 case DimensionsValue::ValueCase::kValueTuple:
367 case DimensionsValue::ValueCase::kValueStr:
368 case DimensionsValue::ValueCase::VALUE_NOT_SET:
369 return 0;
370 }
371}
372
Yangster-mac20877162017-12-22 17:19:39 -0800373} // namespace statsd
374} // namespace os
375} // namespace android