condition_util.cpp revision 7ba8fc357e44ee3bb8e614c202852a1c46a9d4a8
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.child_size() == 0) { 122 allFields->push_back(*rootField); 123 return; 124 } 125 for (int i = 0; i < matcher.child_size(); ++i) { 126 Field* newLeafField = leafField->add_child(); 127 newLeafField->set_field(matcher.child(i).field()); 128 getFieldsFromFieldMatcher(matcher.child(i), rootField, newLeafField, allFields); 129 } 130} 131 132void getFieldsFromFieldMatcher(const FieldMatcher& matcher, std::vector<Field> *allFields) { 133 if (!matcher.has_field()) { 134 return; 135 } 136 Field rootField; 137 rootField.set_field(matcher.field()); 138 getFieldsFromFieldMatcher(matcher, &rootField, &rootField, allFields); 139} 140 141void flattenValueLeaves(const DimensionsValue& value, 142 std::vector<const DimensionsValue*> *allLaves) { 143 switch (value.value_case()) { 144 case DimensionsValue::ValueCase::kValueStr: 145 case DimensionsValue::ValueCase::kValueInt: 146 case DimensionsValue::ValueCase::kValueLong: 147 case DimensionsValue::ValueCase::kValueBool: 148 case DimensionsValue::ValueCase::kValueFloat: 149 case DimensionsValue::ValueCase::VALUE_NOT_SET: 150 allLaves->push_back(&value); 151 break; 152 case DimensionsValue::ValueCase::kValueTuple: 153 for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) { 154 flattenValueLeaves(value.value_tuple().dimensions_value(i), allLaves); 155 } 156 break; 157 } 158} 159 160void getDimensionKeysForCondition( 161 const LogEvent& event, const MetricConditionLink& link, 162 std::vector<HashableDimensionKey> *hashableDimensionKeys) { 163 std::vector<Field> whatFields; 164 getFieldsFromFieldMatcher(link.fields_in_what(), &whatFields); 165 std::vector<Field> conditionFields; 166 getFieldsFromFieldMatcher(link.fields_in_condition(), &conditionFields); 167 168 // TODO(yanglu): here we could simplify the logic to get the leaf value node in what and 169 // directly construct the full condition value tree. 170 std::vector<DimensionsValue> whatValues; 171 getDimensionKeys(event, link.fields_in_what(), &whatValues); 172 173 for (size_t i = 0; i < whatValues.size(); ++i) { 174 std::vector<const DimensionsValue*> whatLeaves; 175 flattenValueLeaves(whatValues[i], &whatLeaves); 176 if (whatLeaves.size() != whatFields.size() || 177 whatLeaves.size() != conditionFields.size()) { 178 ALOGE("Dimensions between what and condition not equal."); 179 return; 180 } 181 FieldValueMap conditionValueMap; 182 for (size_t j = 0; j < whatLeaves.size(); ++j) { 183 DimensionsValue* conditionValue = &conditionValueMap[conditionFields[j]]; 184 *conditionValue = *whatLeaves[i]; 185 if (!setFieldInLeafValueProto(conditionFields[j], conditionValue)) { 186 ALOGE("Not able to reset the field for condition leaf value."); 187 return; 188 } 189 } 190 std::vector<DimensionsValue> conditionValueTrees; 191 findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValueTrees); 192 if (conditionValueTrees.size() != 1) { 193 ALOGE("Not able to find unambiguous field value in condition atom."); 194 continue; 195 } 196 hashableDimensionKeys->push_back(HashableDimensionKey(conditionValueTrees[0])); 197 } 198} 199 200} // namespace statsd 201} // namespace os 202} // namespace android 203