blob: e9875baf58c70671efb35c8b116c25e9d1283531 [file] [log] [blame]
Yao Chencaf339d2017-10-06 16:01:10 -07001/*
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 */
Joe Onorato9fc9edf2017-10-15 20:08:52 -070016
Yao Chen3c0b95c2017-12-16 14:34:20 -080017#define DEBUG false // STOPSHIP if true
Joe Onorato9fc9edf2017-10-15 20:08:52 -070018#include "Log.h"
Yao Chencaf339d2017-10-06 16:01:10 -070019#include "CombinationConditionTracker.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070020
Yao Chencaf339d2017-10-06 16:01:10 -070021namespace android {
22namespace os {
23namespace statsd {
24
Joe Onorato9fc9edf2017-10-15 20:08:52 -070025using std::unordered_map;
26using std::vector;
27
Yangster-mac94e197c2018-01-02 16:03:03 -080028CombinationConditionTracker::CombinationConditionTracker(const int64_t& id, const int index)
29 : ConditionTracker(id, index) {
30 VLOG("creating CombinationConditionTracker %lld", (long long)mConditionId);
Yao Chencaf339d2017-10-06 16:01:10 -070031}
32
33CombinationConditionTracker::~CombinationConditionTracker() {
Yangster-mac94e197c2018-01-02 16:03:03 -080034 VLOG("~CombinationConditionTracker() %lld", (long long)mConditionId);
Yao Chencaf339d2017-10-06 16:01:10 -070035}
36
Stefan Lafon12d01fa2017-12-04 20:56:09 -080037bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConfig,
Yao Chencaf339d2017-10-06 16:01:10 -070038 const vector<sp<ConditionTracker>>& allConditionTrackers,
Yangster-mac94e197c2018-01-02 16:03:03 -080039 const unordered_map<int64_t, int>& conditionIdIndexMap,
tsaichristine6e2e92d2020-05-18 14:39:45 -070040 vector<bool>& stack,
41 vector<ConditionState>& initialConditionCache) {
Yangster-mac94e197c2018-01-02 16:03:03 -080042 VLOG("Combination predicate init() %lld", (long long)mConditionId);
Yao Chencaf339d2017-10-06 16:01:10 -070043 if (mInitialized) {
44 return true;
45 }
46
47 // mark this node as visited in the recursion stack.
48 stack[mIndex] = true;
49
Stefan Lafon12d01fa2017-12-04 20:56:09 -080050 Predicate_Combination combinationCondition = allConditionConfig[mIndex].combination();
Yao Chencaf339d2017-10-06 16:01:10 -070051
52 if (!combinationCondition.has_operation()) {
53 return false;
54 }
55 mLogicalOperation = combinationCondition.operation();
56
Stefan Lafon12d01fa2017-12-04 20:56:09 -080057 if (mLogicalOperation == LogicalOperation::NOT && combinationCondition.predicate_size() != 1) {
Yao Chencaf339d2017-10-06 16:01:10 -070058 return false;
59 }
60
Yangster-mac94e197c2018-01-02 16:03:03 -080061 for (auto child : combinationCondition.predicate()) {
62 auto it = conditionIdIndexMap.find(child);
Yao Chencaf339d2017-10-06 16:01:10 -070063
Yangster-mac94e197c2018-01-02 16:03:03 -080064 if (it == conditionIdIndexMap.end()) {
65 ALOGW("Predicate %lld not found in the config", (long long)child);
Yao Chencaf339d2017-10-06 16:01:10 -070066 return false;
67 }
68
69 int childIndex = it->second;
70 const auto& childTracker = allConditionTrackers[childIndex];
71 // if the child is a visited node in the recursion -> circle detected.
72 if (stack[childIndex]) {
73 ALOGW("Circle detected!!!");
74 return false;
75 }
76
tsaichristine6e2e92d2020-05-18 14:39:45 -070077 bool initChildSucceeded =
78 childTracker->init(allConditionConfig, allConditionTrackers, conditionIdIndexMap,
79 stack, initialConditionCache);
Yao Chencaf339d2017-10-06 16:01:10 -070080
81 if (!initChildSucceeded) {
Yangster-mac94e197c2018-01-02 16:03:03 -080082 ALOGW("Child initialization failed %lld ", (long long)child);
Yao Chencaf339d2017-10-06 16:01:10 -070083 return false;
84 } else {
Tej Singhb7802512019-12-04 17:57:04 -080085 VLOG("Child initialization success %lld ", (long long)child);
Yao Chencaf339d2017-10-06 16:01:10 -070086 }
87
Yangster-mac93694462018-01-22 20:49:31 -080088 if (allConditionTrackers[childIndex]->isSliced()) {
89 setSliced(true);
Yangster13fb7e42018-03-07 17:30:49 -080090 mSlicedChildren.push_back(childIndex);
91 } else {
92 mUnSlicedChildren.push_back(childIndex);
Yangster-mac93694462018-01-22 20:49:31 -080093 }
Yao Chencaf339d2017-10-06 16:01:10 -070094 mChildren.push_back(childIndex);
Yao Chencaf339d2017-10-06 16:01:10 -070095 mTrackerIndex.insert(childTracker->getLogTrackerIndex().begin(),
96 childTracker->getLogTrackerIndex().end());
97 }
98
tsaichristine6e2e92d2020-05-18 14:39:45 -070099 mUnSlicedPartCondition = evaluateCombinationCondition(mUnSlicedChildren, mLogicalOperation,
100 initialConditionCache);
101 initialConditionCache[mIndex] =
102 evaluateCombinationCondition(mChildren, mLogicalOperation, initialConditionCache);
103
Yao Chencaf339d2017-10-06 16:01:10 -0700104 // unmark this node in the recursion stack.
105 stack[mIndex] = false;
106
107 mInitialized = true;
108
109 return true;
110}
111
Yao Chen729093d2017-10-16 10:33:26 -0700112void CombinationConditionTracker::isConditionMet(
Yao Chen8a8d16c2018-02-08 14:50:40 -0800113 const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
Yangster13fb7e42018-03-07 17:30:49 -0800114 const bool isPartialLink,
tsaichristine76853372019-08-06 17:17:03 -0700115 vector<ConditionState>& conditionCache) const {
Yangster-mac93694462018-01-22 20:49:31 -0800116 // So far, this is fine as there is at most one child having sliced output.
Yao Chen729093d2017-10-16 10:33:26 -0700117 for (const int childIndex : mChildren) {
118 if (conditionCache[childIndex] == ConditionState::kNotEvaluated) {
119 allConditions[childIndex]->isConditionMet(conditionParameters, allConditions,
Yangster13fb7e42018-03-07 17:30:49 -0800120 isPartialLink,
tsaichristine76853372019-08-06 17:17:03 -0700121 conditionCache);
Yao Chen729093d2017-10-16 10:33:26 -0700122 }
123 }
124 conditionCache[mIndex] =
125 evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache);
126}
127
Yao Chen967b2052017-11-07 16:36:43 -0800128void CombinationConditionTracker::evaluateCondition(
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700129 const LogEvent& event, const std::vector<MatchingState>& eventMatcherValues,
Yao Chencaf339d2017-10-06 16:01:10 -0700130 const std::vector<sp<ConditionTracker>>& mAllConditions,
Yao Chen729093d2017-10-16 10:33:26 -0700131 std::vector<ConditionState>& nonSlicedConditionCache,
Yao Chen967b2052017-11-07 16:36:43 -0800132 std::vector<bool>& conditionChangedCache) {
Yao Chencaf339d2017-10-06 16:01:10 -0700133 // value is up to date.
Yao Chen729093d2017-10-16 10:33:26 -0700134 if (nonSlicedConditionCache[mIndex] != ConditionState::kNotEvaluated) {
Yao Chen967b2052017-11-07 16:36:43 -0800135 return;
Yao Chencaf339d2017-10-06 16:01:10 -0700136 }
137
138 for (const int childIndex : mChildren) {
Yangster-mac93694462018-01-22 20:49:31 -0800139 // So far, this is fine as there is at most one child having sliced output.
Yao Chen729093d2017-10-16 10:33:26 -0700140 if (nonSlicedConditionCache[childIndex] == ConditionState::kNotEvaluated) {
Yao Chencaf339d2017-10-06 16:01:10 -0700141 const sp<ConditionTracker>& child = mAllConditions[childIndex];
Yao Chen729093d2017-10-16 10:33:26 -0700142 child->evaluateCondition(event, eventMatcherValues, mAllConditions,
Yao Chen967b2052017-11-07 16:36:43 -0800143 nonSlicedConditionCache, conditionChangedCache);
Yao Chencaf339d2017-10-06 16:01:10 -0700144 }
145 }
146
Yao Chen427d3722018-03-22 15:21:52 -0700147 ConditionState newCondition =
148 evaluateCombinationCondition(mChildren, mLogicalOperation, nonSlicedConditionCache);
Yao Chen967b2052017-11-07 16:36:43 -0800149 if (!mSliced) {
tsaichristinefe469732020-05-19 14:53:11 -0700150 bool nonSlicedChanged = (mUnSlicedPartCondition != newCondition);
151 mUnSlicedPartCondition = newCondition;
Yao Chencaf339d2017-10-06 16:01:10 -0700152
tsaichristinefe469732020-05-19 14:53:11 -0700153 nonSlicedConditionCache[mIndex] = mUnSlicedPartCondition;
Yao Chen967b2052017-11-07 16:36:43 -0800154 conditionChangedCache[mIndex] = nonSlicedChanged;
155 } else {
tsaichristinefe469732020-05-19 14:53:11 -0700156 mUnSlicedPartCondition = evaluateCombinationCondition(mUnSlicedChildren, mLogicalOperation,
157 nonSlicedConditionCache);
Yangster13fb7e42018-03-07 17:30:49 -0800158
Yao Chen729093d2017-10-16 10:33:26 -0700159 for (const int childIndex : mChildren) {
160 // If any of the sliced condition in children condition changes, the combination
161 // condition may be changed too.
Yao Chen967b2052017-11-07 16:36:43 -0800162 if (conditionChangedCache[childIndex]) {
163 conditionChangedCache[mIndex] = true;
Yao Chen729093d2017-10-16 10:33:26 -0700164 break;
165 }
166 }
Yao Chen427d3722018-03-22 15:21:52 -0700167 nonSlicedConditionCache[mIndex] = newCondition;
Yangster-mac86179502018-01-23 15:47:15 -0800168 VLOG("CombinationPredicate %lld sliced may changed? %d", (long long)mConditionId,
Yangster-mac94e197c2018-01-02 16:03:03 -0800169 conditionChangedCache[mIndex] == true);
Yao Chen729093d2017-10-16 10:33:26 -0700170 }
Yao Chencaf339d2017-10-06 16:01:10 -0700171}
172
Yangster13fb7e42018-03-07 17:30:49 -0800173bool CombinationConditionTracker::equalOutputDimensions(
174 const std::vector<sp<ConditionTracker>>& allConditions,
175 const vector<Matcher>& dimensions) const {
176 if (mSlicedChildren.size() != 1 ||
177 mSlicedChildren.front() >= (int)allConditions.size() ||
178 mLogicalOperation != LogicalOperation::AND) {
179 return false;
180 }
181 const sp<ConditionTracker>& slicedChild = allConditions.at(mSlicedChildren.front());
182 return slicedChild->equalOutputDimensions(allConditions, dimensions);
183}
184
Yao Chencaf339d2017-10-06 16:01:10 -0700185} // namespace statsd
186} // namespace os
187} // namespace android