• 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  * The value of the FieldValue is output.
170  */
171 bool filterValues(const Matcher& matcherField, const std::vector<FieldValue>& values,
172                   FieldValue* output);
173 
174 /**
175  * Creating HashableDimensionKeys from FieldValues using matcher.
176  *
177  * This function may make modifications to the Field if the matcher has Position=FIRST,LAST or ALL
178  * in it. This is because: for example, when we create dimension from last uid in attribution chain,
179  * In one event, uid 1000 is at position 5 and it's the last
180  * In another event, uid 1000 is at position 6, and it's the last
181  * these 2 events should be mapped to the same dimension.  So we will remove the original position
182  * from the dimension key for the uid field (by applying 0x80 bit mask).
183  */
184 bool filterValues(const std::vector<Matcher>& matcherFields, const std::vector<FieldValue>& values,
185                   HashableDimensionKey* output);
186 
187 /**
188  * Filters FieldValues to create HashableDimensionKey using dimensions matcher fields and create
189  *  vector of value indices using values matcher fields.
190  *
191  * This function may make modifications to the Field if the matcher has Position=FIRST,LAST or ALL
192  * in it. This is because: for example, when we create dimension from last uid in attribution chain,
193  * In one event, uid 1000 is at position 5 and it's the last
194  * In another event, uid 1000 is at position 6, and it's the last
195  * these 2 events should be mapped to the same dimension.  So we will remove the original position
196  * from the dimension key for the uid field (by applying 0x80 bit mask).
197  *
198  * dimKeyMatcherFields: the matchers for each dimension field
199  * valueMatcherFields: the matchers for each value field
200  * values: FieldValues being filtered by the matchers
201  * key: HashableDimensionKey containing the values filtered by the dimKeyMatcherFields
202  * valueIndices: index position of each matched FieldValue corresponding to the valueMatcherFields
203  */
204 bool filterValues(const std::vector<Matcher>& dimKeyMatcherFields,
205                   const std::vector<Matcher>& valueMatcherFields,
206                   const std::vector<FieldValue>& values, HashableDimensionKey& key,
207                   std::vector<int>& valueIndices);
208 
209 /**
210  * Creating HashableDimensionKeys from State Primary Keys in FieldValues.
211  *
212  * This function may make modifications to the Field if the matcher has Position=FIRST,LAST or ALL
213  * in it. This is because: for example, when we create dimension from last uid in attribution chain,
214  * In one event, uid 1000 is at position 5 and it's the last
215  * In another event, uid 1000 is at position 6, and it's the last
216  * these 2 events should be mapped to the same dimension.  So we will remove the original position
217  * from the dimension key for the uid field (by applying 0x80 bit mask).
218  */
219 bool filterPrimaryKey(const std::vector<FieldValue>& values, HashableDimensionKey* output);
220 
221 /**
222  * Filter the values from FieldValues using the matchers.
223  *
224  * In contrast to the above function, this function will not do any modification to the original
225  * data. Considering it as taking a snapshot on the atom event.
226  */
227 void filterGaugeValues(const std::vector<Matcher>& matchers, const std::vector<FieldValue>& values,
228                        std::vector<FieldValue>* output);
229 
230 void getDimensionForCondition(const std::vector<FieldValue>& eventValues,
231                               const Metric2Condition& links,
232                               HashableDimensionKey* conditionDimension);
233 
234 /**
235  * Get dimension values using metric's "what" fields and fill statePrimaryKey's
236  * mField information using "state" fields.
237  */
238 void getDimensionForState(const std::vector<FieldValue>& eventValues, const Metric2State& link,
239                           HashableDimensionKey* statePrimaryKey);
240 
241 /**
242  * Returns true if the primaryKey values are a subset of the whatKey values.
243  * The values from the primaryKey come from the state atom, so we need to
244  * check that a link exists between the state atom field and what atom field.
245  *
246  * Example:
247  * whatKey = [Atom: 10, {uid: 1005, wakelock_name: "compose"}]
248  * statePrimaryKey = [Atom: 27, {uid: 1005}]
249  * Returns true IF one of the Metric2State links Atom 10's uid to Atom 27's uid
250  *
251  * Example:
252  * whatKey = [Atom: 10, {uid: 1005, wakelock_name: "compose"}]
253  * statePrimaryKey = [Atom: 59, {uid: 1005, package_name: "system"}]
254  * Returns false
255  */
256 bool containsLinkedStateValues(const HashableDimensionKey& whatKey,
257                                const HashableDimensionKey& primaryKey,
258                                const std::vector<Metric2State>& stateLinks,
259                                const int32_t stateAtomId);
260 
261 /**
262  * Returns true if there is a Metric2State link that links the stateField and
263  * the metricField (they are equal fields from different atoms).
264  */
265 bool linked(const std::vector<Metric2State>& stateLinks, const int32_t stateAtomId,
266             const Field& stateField, const Field& metricField);
267 }  // namespace statsd
268 }  // namespace os
269 }  // namespace android
270 
271 namespace std {
272 
273 using android::os::statsd::AtomDimensionKey;
274 using android::os::statsd::HashableDimensionKey;
275 using android::os::statsd::MetricDimensionKey;
276 
277 template <>
278 struct hash<HashableDimensionKey> {
279     std::size_t operator()(const HashableDimensionKey& key) const {
280         return hashDimension(key);
281     }
282 };
283 
284 template <>
285 struct hash<MetricDimensionKey> {
286     std::size_t operator()(const MetricDimensionKey& key) const {
287         android::hash_t hash = hashDimension(key.getDimensionKeyInWhat());
288         hash = android::JenkinsHashMix(hash, hashDimension(key.getStateValuesKey()));
289         return android::JenkinsHashWhiten(hash);
290     }
291 };
292 
293 template <>
294 struct hash<AtomDimensionKey> {
295     std::size_t operator()(const AtomDimensionKey& key) const {
296         android::hash_t hash = hashDimension(key.getAtomFieldValues());
297         hash = android::JenkinsHashMix(hash, key.getAtomTag());
298         return android::JenkinsHashWhiten(hash);
299     }
300 };
301 }  // namespace std
302