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