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 struct Metric2Condition { 33 int64_t conditionId; 34 std::vector<Matcher> metricFields; 35 std::vector<Matcher> conditionFields; 36 }; 37 38 struct Metric2State { 39 int32_t stateAtomId; 40 std::vector<Matcher> metricFields; 41 std::vector<Matcher> stateFields; 42 }; 43 44 class HashableDimensionKey { 45 public: HashableDimensionKey(const std::vector<FieldValue> & values)46 explicit HashableDimensionKey(const std::vector<FieldValue>& values) { 47 mValues = values; 48 } 49 HashableDimensionKey()50 HashableDimensionKey() {}; 51 HashableDimensionKey(const HashableDimensionKey & that)52 HashableDimensionKey(const HashableDimensionKey& that) : mValues(that.getValues()){}; 53 addValue(const FieldValue & value)54 inline void addValue(const FieldValue& value) { 55 mValues.push_back(value); 56 } 57 getValues()58 inline const std::vector<FieldValue>& getValues() const { 59 return mValues; 60 } 61 mutableValues()62 inline std::vector<FieldValue>* mutableValues() { 63 return &mValues; 64 } 65 mutableValue(size_t i)66 inline FieldValue* mutableValue(size_t i) { 67 if (i >= 0 && i < mValues.size()) { 68 return &(mValues[i]); 69 } 70 return nullptr; 71 } 72 73 StatsDimensionsValueParcel toStatsDimensionsValueParcel() const; 74 75 std::string toString() const; 76 77 bool operator!=(const HashableDimensionKey& that) const; 78 79 bool operator==(const HashableDimensionKey& that) const; 80 81 bool operator<(const HashableDimensionKey& that) const; 82 83 bool contains(const HashableDimensionKey& that) const; 84 85 private: 86 std::vector<FieldValue> mValues; 87 }; 88 89 class MetricDimensionKey { 90 public: MetricDimensionKey(const HashableDimensionKey & dimensionKeyInWhat,const HashableDimensionKey & stateValuesKey)91 explicit MetricDimensionKey(const HashableDimensionKey& dimensionKeyInWhat, 92 const HashableDimensionKey& stateValuesKey) 93 : mDimensionKeyInWhat(dimensionKeyInWhat), mStateValuesKey(stateValuesKey){}; 94 MetricDimensionKey()95 MetricDimensionKey(){}; 96 MetricDimensionKey(const MetricDimensionKey & that)97 MetricDimensionKey(const MetricDimensionKey& that) 98 : mDimensionKeyInWhat(that.getDimensionKeyInWhat()), 99 mStateValuesKey(that.getStateValuesKey()){}; 100 101 MetricDimensionKey& operator=(const MetricDimensionKey& from) = default; 102 103 std::string toString() const; 104 getDimensionKeyInWhat()105 inline const HashableDimensionKey& getDimensionKeyInWhat() const { 106 return mDimensionKeyInWhat; 107 } 108 getStateValuesKey()109 inline const HashableDimensionKey& getStateValuesKey() const { 110 return mStateValuesKey; 111 } 112 getMutableStateValuesKey()113 inline HashableDimensionKey* getMutableStateValuesKey() { 114 return &mStateValuesKey; 115 } 116 setStateValuesKey(const HashableDimensionKey & key)117 inline void setStateValuesKey(const HashableDimensionKey& key) { 118 mStateValuesKey = key; 119 } 120 hasStateValuesKey()121 bool hasStateValuesKey() const { 122 return mStateValuesKey.getValues().size() > 0; 123 } 124 125 bool operator==(const MetricDimensionKey& that) const; 126 127 bool operator<(const MetricDimensionKey& that) const; 128 129 private: 130 HashableDimensionKey mDimensionKeyInWhat; 131 HashableDimensionKey mStateValuesKey; 132 }; 133 134 android::hash_t hashDimension(const HashableDimensionKey& key); 135 136 /** 137 * Returns true if a FieldValue field matches the matcher field. 138 * The value of the FieldValue is output. 139 */ 140 bool filterValues(const Matcher& matcherField, const std::vector<FieldValue>& values, 141 FieldValue* output); 142 143 /** 144 * Creating HashableDimensionKeys from FieldValues using matcher. 145 * 146 * This function may make modifications to the Field if the matcher has Position=FIRST,LAST or ALL 147 * in it. This is because: for example, when we create dimension from last uid in attribution chain, 148 * In one event, uid 1000 is at position 5 and it's the last 149 * In another event, uid 1000 is at position 6, and it's the last 150 * these 2 events should be mapped to the same dimension. So we will remove the original position 151 * from the dimension key for the uid field (by applying 0x80 bit mask). 152 */ 153 bool filterValues(const std::vector<Matcher>& matcherFields, const std::vector<FieldValue>& values, 154 HashableDimensionKey* output); 155 156 /** 157 * Creating HashableDimensionKeys from State Primary Keys in FieldValues. 158 * 159 * This function may make modifications to the Field if the matcher has Position=FIRST,LAST or ALL 160 * in it. This is because: for example, when we create dimension from last uid in attribution chain, 161 * In one event, uid 1000 is at position 5 and it's the last 162 * In another event, uid 1000 is at position 6, and it's the last 163 * these 2 events should be mapped to the same dimension. So we will remove the original position 164 * from the dimension key for the uid field (by applying 0x80 bit mask). 165 */ 166 bool filterPrimaryKey(const std::vector<FieldValue>& values, HashableDimensionKey* output); 167 168 /** 169 * Filter the values from FieldValues using the matchers. 170 * 171 * In contrast to the above function, this function will not do any modification to the original 172 * data. Considering it as taking a snapshot on the atom event. 173 */ 174 void filterGaugeValues(const std::vector<Matcher>& matchers, const std::vector<FieldValue>& values, 175 std::vector<FieldValue>* output); 176 177 void getDimensionForCondition(const std::vector<FieldValue>& eventValues, 178 const Metric2Condition& links, 179 HashableDimensionKey* conditionDimension); 180 181 /** 182 * Get dimension values using metric's "what" fields and fill statePrimaryKey's 183 * mField information using "state" fields. 184 */ 185 void getDimensionForState(const std::vector<FieldValue>& eventValues, const Metric2State& link, 186 HashableDimensionKey* statePrimaryKey); 187 188 /** 189 * Returns true if the primaryKey values are a subset of the whatKey values. 190 * The values from the primaryKey come from the state atom, so we need to 191 * check that a link exists between the state atom field and what atom field. 192 * 193 * Example: 194 * whatKey = [Atom: 10, {uid: 1005, wakelock_name: "compose"}] 195 * statePrimaryKey = [Atom: 27, {uid: 1005}] 196 * Returns true IF one of the Metric2State links Atom 10's uid to Atom 27's uid 197 * 198 * Example: 199 * whatKey = [Atom: 10, {uid: 1005, wakelock_name: "compose"}] 200 * statePrimaryKey = [Atom: 59, {uid: 1005, package_name: "system"}] 201 * Returns false 202 */ 203 bool containsLinkedStateValues(const HashableDimensionKey& whatKey, 204 const HashableDimensionKey& primaryKey, 205 const std::vector<Metric2State>& stateLinks, 206 const int32_t stateAtomId); 207 208 /** 209 * Returns true if there is a Metric2State link that links the stateField and 210 * the metricField (they are equal fields from different atoms). 211 */ 212 bool linked(const std::vector<Metric2State>& stateLinks, const int32_t stateAtomId, 213 const Field& stateField, const Field& metricField); 214 } // namespace statsd 215 } // namespace os 216 } // namespace android 217 218 namespace std { 219 220 using android::os::statsd::HashableDimensionKey; 221 using android::os::statsd::MetricDimensionKey; 222 223 template <> 224 struct hash<HashableDimensionKey> { 225 std::size_t operator()(const HashableDimensionKey& key) const { 226 return hashDimension(key); 227 } 228 }; 229 230 template <> 231 struct hash<MetricDimensionKey> { 232 std::size_t operator()(const MetricDimensionKey& key) const { 233 android::hash_t hash = hashDimension(key.getDimensionKeyInWhat()); 234 hash = android::JenkinsHashMix(hash, hashDimension(key.getStateValuesKey())); 235 return android::JenkinsHashWhiten(hash); 236 } 237 }; 238 } // namespace std 239