• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #pragma once
18 
19 #include <aidl/android/os/StatsDimensionsValueParcel.h>
20 #include <utils/JenkinsHash.h>
21 #include <vector>
22 #include "android-base/stringprintf.h"
23 #include "FieldValue.h"
24 #include "logd/LogEvent.h"
25 
26 namespace android {
27 namespace os {
28 namespace statsd {
29 
30 using ::aidl::android::os::StatsDimensionsValueParcel;
31 
32 // These constants must be kept in sync with those in StatsDimensionsValue.java
33 inline constexpr int STATS_DIMENSIONS_VALUE_STRING_TYPE = 2;
34 inline constexpr int STATS_DIMENSIONS_VALUE_INT_TYPE = 3;
35 inline constexpr int STATS_DIMENSIONS_VALUE_LONG_TYPE = 4;
36 // inline constexpr int STATS_DIMENSIONS_VALUE_BOOL_TYPE = 5; (commented out because
37 // unused -- statsd does not correctly support bool types)
38 inline constexpr int STATS_DIMENSIONS_VALUE_FLOAT_TYPE = 6;
39 inline constexpr int STATS_DIMENSIONS_VALUE_TUPLE_TYPE = 7;
40 
41 struct Metric2Condition {
42     int64_t conditionId;
43     std::vector<Matcher> metricFields;
44     std::vector<Matcher> conditionFields;
45 };
46 
47 struct Metric2State {
48     int32_t stateAtomId;
49     std::vector<Matcher> metricFields;
50     std::vector<Matcher> stateFields;
51 };
52 
53 class HashableDimensionKey {
54 public:
HashableDimensionKey(const std::vector<FieldValue> & values)55     explicit HashableDimensionKey(const std::vector<FieldValue>& values) {
56         mValues = values;
57     }
58 
HashableDimensionKey()59     HashableDimensionKey() {};
60 
HashableDimensionKey(const HashableDimensionKey & that)61     HashableDimensionKey(const HashableDimensionKey& that) : mValues(that.getValues()){};
62 
addValue(const FieldValue & value)63     inline void addValue(const FieldValue& value) {
64         mValues.push_back(value);
65     }
66 
getValues()67     inline const std::vector<FieldValue>& getValues() const {
68         return mValues;
69     }
70 
mutableValues()71     inline std::vector<FieldValue>* mutableValues() {
72         return &mValues;
73     }
74 
mutableValue(size_t i)75     inline FieldValue* mutableValue(size_t i) {
76         if (i >= 0 && i < mValues.size()) {
77             return &(mValues[i]);
78         }
79         return nullptr;
80     }
81 
82     StatsDimensionsValueParcel toStatsDimensionsValueParcel() const;
83 
84     std::string toString() const;
85 
86     bool operator!=(const HashableDimensionKey& that) const;
87 
88     bool operator==(const HashableDimensionKey& that) const;
89 
90     bool operator<(const HashableDimensionKey& that) const;
91 
92     bool contains(const HashableDimensionKey& that) const;
93 
94 private:
95     std::vector<FieldValue> mValues;
96 };
97 
98 class MetricDimensionKey {
99 public:
MetricDimensionKey(const HashableDimensionKey & dimensionKeyInWhat,const HashableDimensionKey & stateValuesKey)100     explicit MetricDimensionKey(const HashableDimensionKey& dimensionKeyInWhat,
101                                 const HashableDimensionKey& stateValuesKey)
102         : mDimensionKeyInWhat(dimensionKeyInWhat), mStateValuesKey(stateValuesKey){};
103 
MetricDimensionKey()104     MetricDimensionKey(){};
105 
MetricDimensionKey(const MetricDimensionKey & that)106     MetricDimensionKey(const MetricDimensionKey& that)
107         : mDimensionKeyInWhat(that.getDimensionKeyInWhat()),
108           mStateValuesKey(that.getStateValuesKey()){};
109 
110     MetricDimensionKey& operator=(const MetricDimensionKey& from) = default;
111 
112     std::string toString() const;
113 
getDimensionKeyInWhat()114     inline const HashableDimensionKey& getDimensionKeyInWhat() const {
115         return mDimensionKeyInWhat;
116     }
117 
getStateValuesKey()118     inline const HashableDimensionKey& getStateValuesKey() const {
119         return mStateValuesKey;
120     }
121 
getMutableStateValuesKey()122     inline HashableDimensionKey* getMutableStateValuesKey() {
123         return &mStateValuesKey;
124     }
125 
setStateValuesKey(const HashableDimensionKey & key)126     inline void setStateValuesKey(const HashableDimensionKey& key) {
127         mStateValuesKey = key;
128     }
129 
hasStateValuesKey()130     bool hasStateValuesKey() const {
131         return mStateValuesKey.getValues().size() > 0;
132     }
133 
134     bool operator==(const MetricDimensionKey& that) const;
135 
136     bool operator<(const MetricDimensionKey& that) const;
137 
138 private:
139     HashableDimensionKey mDimensionKeyInWhat;
140     HashableDimensionKey mStateValuesKey;
141 };
142 
143 class AtomDimensionKey {
144 public:
AtomDimensionKey(const int32_t atomTag,const HashableDimensionKey & atomFieldValues)145     explicit AtomDimensionKey(const int32_t atomTag, const HashableDimensionKey& atomFieldValues)
146         : mAtomTag(atomTag), mAtomFieldValues(atomFieldValues){};
147 
AtomDimensionKey()148     AtomDimensionKey(){};
149 
getAtomTag()150     inline int32_t getAtomTag() const {
151         return mAtomTag;
152     }
153 
getAtomFieldValues()154     inline const HashableDimensionKey& getAtomFieldValues() const {
155         return mAtomFieldValues;
156     }
157 
158     bool operator==(const AtomDimensionKey& that) const;
159 
160 private:
161     int32_t mAtomTag;
162     HashableDimensionKey mAtomFieldValues;
163 };
164 
165 android::hash_t hashDimension(const HashableDimensionKey& key);
166 
167 /**
168  * Returns true if a FieldValue field matches the matcher field.
169  * This function can only be used to match one field (i.e. matcher with position ALL will return
170  * false). The value of the FieldValue is output.
171  */
172 bool filterValues(const Matcher& matcherField, const std::vector<FieldValue>& values,
173                   FieldValue* output);
174 
175 /**
176  * Creating HashableDimensionKeys from FieldValues using matcher.
177  *
178  * This function may make modifications to the Field if the matcher has Position=FIRST,LAST or ALL
179  * in it. This is because: for example, when we create dimension from last uid in attribution chain,
180  * In one event, uid 1000 is at position 5 and it's the last
181  * In another event, uid 1000 is at position 6, and it's the last
182  * these 2 events should be mapped to the same dimension.  So we will remove the original position
183  * from the dimension key for the uid field (by applying 0x80 bit mask).
184  */
185 bool filterValues(const std::vector<Matcher>& matcherFields, const std::vector<FieldValue>& values,
186                   HashableDimensionKey* output);
187 
188 /**
189  * Filters FieldValues to create HashableDimensionKey using dimensions matcher fields and create
190  *  vector of value indices using values matcher fields.
191  *
192  * This function may make modifications to the Field if the matcher has Position=FIRST,LAST or ALL
193  * in it. This is because: for example, when we create dimension from last uid in attribution chain,
194  * In one event, uid 1000 is at position 5 and it's the last
195  * In another event, uid 1000 is at position 6, and it's the last
196  * these 2 events should be mapped to the same dimension.  So we will remove the original position
197  * from the dimension key for the uid field (by applying 0x80 bit mask).
198  *
199  * dimKeyMatcherFields: the matchers for each dimension field
200  * valueMatcherFields: the matchers for each value field
201  * values: FieldValues being filtered by the matchers
202  * key: HashableDimensionKey containing the values filtered by the dimKeyMatcherFields
203  * valueIndices: index position of each matched FieldValue corresponding to the valueMatcherFields
204  */
205 bool filterValues(const std::vector<Matcher>& dimKeyMatcherFields,
206                   const std::vector<Matcher>& valueMatcherFields,
207                   const std::vector<FieldValue>& values, HashableDimensionKey& key,
208                   std::vector<int>& valueIndices);
209 
210 /**
211  * Creating HashableDimensionKeys from State Primary Keys in FieldValues.
212  *
213  * This function may make modifications to the Field if the matcher has Position=FIRST,LAST or ALL
214  * in it. This is because: for example, when we create dimension from last uid in attribution chain,
215  * In one event, uid 1000 is at position 5 and it's the last
216  * In another event, uid 1000 is at position 6, and it's the last
217  * these 2 events should be mapped to the same dimension.  So we will remove the original position
218  * from the dimension key for the uid field (by applying 0x80 bit mask).
219  */
220 bool filterPrimaryKey(const std::vector<FieldValue>& values, HashableDimensionKey* output);
221 
222 /**
223  * Filter the values from FieldValues using the matchers.
224  *
225  * In contrast to the above function, this function will not do any modification to the original
226  * data. Considering it as taking a snapshot on the atom event.
227  */
228 void filterGaugeValues(const std::vector<Matcher>& matchers, const std::vector<FieldValue>& values,
229                        std::vector<FieldValue>* output);
230 
231 void getDimensionForCondition(const std::vector<FieldValue>& eventValues,
232                               const Metric2Condition& links,
233                               HashableDimensionKey* conditionDimension);
234 
235 /**
236  * Get dimension values using metric's "what" fields and fill statePrimaryKey's
237  * mField information using "state" fields.
238  */
239 void getDimensionForState(const std::vector<FieldValue>& eventValues, const Metric2State& link,
240                           HashableDimensionKey* statePrimaryKey);
241 
242 /**
243  * Returns true if the primaryKey values are a subset of the whatKey values.
244  * The values from the primaryKey come from the state atom, so we need to
245  * check that a link exists between the state atom field and what atom field.
246  *
247  * Example:
248  * whatKey = [Atom: 10, {uid: 1005, wakelock_name: "compose"}]
249  * statePrimaryKey = [Atom: 27, {uid: 1005}]
250  * Returns true IF one of the Metric2State links Atom 10's uid to Atom 27's uid
251  *
252  * Example:
253  * whatKey = [Atom: 10, {uid: 1005, wakelock_name: "compose"}]
254  * statePrimaryKey = [Atom: 59, {uid: 1005, package_name: "system"}]
255  * Returns false
256  */
257 bool containsLinkedStateValues(const HashableDimensionKey& whatKey,
258                                const HashableDimensionKey& primaryKey,
259                                const std::vector<Metric2State>& stateLinks,
260                                const int32_t stateAtomId);
261 
262 /**
263  * Returns true if there is a Metric2State link that links the stateField and
264  * the metricField (they are equal fields from different atoms).
265  */
266 bool linked(const std::vector<Metric2State>& stateLinks, const int32_t stateAtomId,
267             const Field& stateField, const Field& metricField);
268 }  // namespace statsd
269 }  // namespace os
270 }  // namespace android
271 
272 namespace std {
273 
274 using android::os::statsd::AtomDimensionKey;
275 using android::os::statsd::HashableDimensionKey;
276 using android::os::statsd::MetricDimensionKey;
277 
278 template <>
279 struct hash<HashableDimensionKey> {
280     std::size_t operator()(const HashableDimensionKey& key) const {
281         return hashDimension(key);
282     }
283 };
284 
285 template <>
286 struct hash<MetricDimensionKey> {
287     std::size_t operator()(const MetricDimensionKey& key) const {
288         android::hash_t hash = hashDimension(key.getDimensionKeyInWhat());
289         hash = android::JenkinsHashMix(hash, hashDimension(key.getStateValuesKey()));
290         return android::JenkinsHashWhiten(hash);
291     }
292 };
293 
294 template <>
295 struct hash<AtomDimensionKey> {
296     std::size_t operator()(const AtomDimensionKey& key) const {
297         android::hash_t hash = hashDimension(key.getAtomFieldValues());
298         hash = android::JenkinsHashMix(hash, key.getAtomTag());
299         return android::JenkinsHashWhiten(hash);
300     }
301 };
302 }  // namespace std
303