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