condition_util.cpp revision 9369446f0b04945d6674550728ae81196d6fb5c2
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#include "Log.h" 18 19#include "condition_util.h" 20 21#include <log/event_tag_map.h> 22#include <log/log_event_list.h> 23#include <log/logprint.h> 24#include <utils/Errors.h> 25#include <unordered_map> 26#include "../matchers/matcher_util.h" 27#include "ConditionTracker.h" 28#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" 29#include "stats_util.h" 30#include "dimension.h" 31 32namespace android { 33namespace os { 34namespace statsd { 35 36using std::set; 37using std::string; 38using std::unordered_map; 39using std::vector; 40 41 42ConditionState evaluateCombinationCondition(const std::vector<int>& children, 43 const LogicalOperation& operation, 44 const std::vector<ConditionState>& conditionCache) { 45 ConditionState newCondition; 46 47 bool hasUnknown = false; 48 bool hasFalse = false; 49 bool hasTrue = false; 50 51 for (auto childIndex : children) { 52 ConditionState childState = conditionCache[childIndex]; 53 if (childState == ConditionState::kUnknown) { 54 hasUnknown = true; 55 break; 56 } 57 if (childState == ConditionState::kFalse) { 58 hasFalse = true; 59 } 60 if (childState == ConditionState::kTrue) { 61 hasTrue = true; 62 } 63 } 64 65 // If any child condition is in unknown state, the condition is unknown too. 66 if (hasUnknown) { 67 return ConditionState::kUnknown; 68 } 69 70 switch (operation) { 71 case LogicalOperation::AND: { 72 newCondition = hasFalse ? ConditionState::kFalse : ConditionState::kTrue; 73 break; 74 } 75 case LogicalOperation::OR: { 76 newCondition = hasTrue ? ConditionState::kTrue : ConditionState::kFalse; 77 break; 78 } 79 case LogicalOperation::NOT: 80 newCondition = (conditionCache[children[0]] == ConditionState::kFalse) 81 ? ConditionState::kTrue 82 : ConditionState::kFalse; 83 break; 84 case LogicalOperation::NAND: 85 newCondition = hasFalse ? ConditionState::kTrue : ConditionState::kFalse; 86 break; 87 case LogicalOperation::NOR: 88 newCondition = hasTrue ? ConditionState::kFalse : ConditionState::kTrue; 89 break; 90 case LogicalOperation::LOGICAL_OPERATION_UNSPECIFIED: 91 newCondition = ConditionState::kFalse; 92 break; 93 } 94 return newCondition; 95} 96 97ConditionState operator|(ConditionState l, ConditionState r) { 98 return l >= r ? l : r; 99} 100 101void OrConditionState(const std::vector<ConditionState>& ref, vector<ConditionState> * ored) { 102 if (ref.size() != ored->size()) { 103 return; 104 } 105 for (size_t i = 0; i < ored->size(); ++i) { 106 ored->at(i) = ored->at(i) | ref.at(i); 107 } 108} 109 110void OrBooleanVector(const std::vector<bool>& ref, vector<bool> * ored) { 111 if (ref.size() != ored->size()) { 112 return; 113 } 114 for (size_t i = 0; i < ored->size(); ++i) { 115 ored->at(i) = ored->at(i) | ref.at(i); 116 } 117} 118 119void getFieldsFromFieldMatcher(const FieldMatcher& matcher, Field* rootField, Field* leafField, 120 std::vector<Field> *allFields) { 121 if (matcher.has_position()) { 122 leafField->set_position_index(0); 123 } 124 if (matcher.child_size() == 0) { 125 allFields->push_back(*rootField); 126 return; 127 } 128 for (int i = 0; i < matcher.child_size(); ++i) { 129 Field* newLeafField = leafField->add_child(); 130 newLeafField->set_field(matcher.child(i).field()); 131 getFieldsFromFieldMatcher(matcher.child(i), rootField, newLeafField, allFields); 132 } 133} 134 135void getFieldsFromFieldMatcher(const FieldMatcher& matcher, std::vector<Field> *allFields) { 136 if (!matcher.has_field()) { 137 return; 138 } 139 Field rootField; 140 rootField.set_field(matcher.field()); 141 getFieldsFromFieldMatcher(matcher, &rootField, &rootField, allFields); 142} 143 144void flattenValueLeaves(const DimensionsValue& value, 145 std::vector<const DimensionsValue*> *allLaves) { 146 switch (value.value_case()) { 147 case DimensionsValue::ValueCase::kValueStr: 148 case DimensionsValue::ValueCase::kValueInt: 149 case DimensionsValue::ValueCase::kValueLong: 150 case DimensionsValue::ValueCase::kValueBool: 151 case DimensionsValue::ValueCase::kValueFloat: 152 case DimensionsValue::ValueCase::VALUE_NOT_SET: 153 allLaves->push_back(&value); 154 break; 155 case DimensionsValue::ValueCase::kValueTuple: 156 for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) { 157 flattenValueLeaves(value.value_tuple().dimensions_value(i), allLaves); 158 } 159 break; 160 } 161} 162 163void getDimensionKeysForCondition( 164 const LogEvent& event, const MetricConditionLink& link, 165 std::vector<HashableDimensionKey> *hashableDimensionKeys) { 166 std::vector<Field> whatFields; 167 getFieldsFromFieldMatcher(link.fields_in_what(), &whatFields); 168 std::vector<Field> conditionFields; 169 getFieldsFromFieldMatcher(link.fields_in_condition(), &conditionFields); 170 171 // TODO(yanglu): here we could simplify the logic to get the leaf value node in what and 172 // directly construct the full condition value tree. 173 std::vector<DimensionsValue> whatValues; 174 getDimensionKeys(event, link.fields_in_what(), &whatValues); 175 176 for (size_t i = 0; i < whatValues.size(); ++i) { 177 std::vector<const DimensionsValue*> whatLeaves; 178 flattenValueLeaves(whatValues[i], &whatLeaves); 179 if (whatLeaves.size() != whatFields.size() || 180 whatLeaves.size() != conditionFields.size()) { 181 ALOGE("Dimensions between what and condition not equal."); 182 return; 183 } 184 FieldValueMap conditionValueMap; 185 for (size_t j = 0; j < whatLeaves.size(); ++j) { 186 DimensionsValue* conditionValue = &conditionValueMap[conditionFields[j]]; 187 *conditionValue = *whatLeaves[i]; 188 if (!setFieldInLeafValueProto(conditionFields[j], conditionValue)) { 189 ALOGE("Not able to reset the field for condition leaf value."); 190 return; 191 } 192 } 193 std::vector<DimensionsValue> conditionValueTrees; 194 findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValueTrees); 195 if (conditionValueTrees.size() != 1) { 196 ALOGE("Not able to find unambiguous field value in condition atom."); 197 continue; 198 } 199 hashableDimensionKeys->push_back(HashableDimensionKey(conditionValueTrees[0])); 200 } 201} 202 203} // namespace statsd 204} // namespace os 205} // namespace android 206