blob: c829ccd11ec95ef36f880ed74c5ac551142ac116 [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,
Yao Chencaf339d2017-10-06 16:01:10 -070040 vector<bool>& stack) {
Yangster-mac94e197c2018-01-02 16:03:03 -080041 VLOG("Combination predicate init() %lld", (long long)mConditionId);
Yao Chencaf339d2017-10-06 16:01:10 -070042 if (mInitialized) {
43 return true;
44 }
45
46 // mark this node as visited in the recursion stack.
47 stack[mIndex] = true;
48
Stefan Lafon12d01fa2017-12-04 20:56:09 -080049 Predicate_Combination combinationCondition = allConditionConfig[mIndex].combination();
Yao Chencaf339d2017-10-06 16:01:10 -070050
51 if (!combinationCondition.has_operation()) {
52 return false;
53 }
54 mLogicalOperation = combinationCondition.operation();
55
Stefan Lafon12d01fa2017-12-04 20:56:09 -080056 if (mLogicalOperation == LogicalOperation::NOT && combinationCondition.predicate_size() != 1) {
Yao Chencaf339d2017-10-06 16:01:10 -070057 return false;
58 }
59
Yangster-mac94e197c2018-01-02 16:03:03 -080060 for (auto child : combinationCondition.predicate()) {
61 auto it = conditionIdIndexMap.find(child);
Yao Chencaf339d2017-10-06 16:01:10 -070062
Yangster-mac94e197c2018-01-02 16:03:03 -080063 if (it == conditionIdIndexMap.end()) {
64 ALOGW("Predicate %lld not found in the config", (long long)child);
Yao Chencaf339d2017-10-06 16:01:10 -070065 return false;
66 }
67
68 int childIndex = it->second;
69 const auto& childTracker = allConditionTrackers[childIndex];
70 // if the child is a visited node in the recursion -> circle detected.
71 if (stack[childIndex]) {
72 ALOGW("Circle detected!!!");
73 return false;
74 }
75
Yangster-mac93694462018-01-22 20:49:31 -080076
Yao Chencaf339d2017-10-06 16:01:10 -070077 bool initChildSucceeded = childTracker->init(allConditionConfig, allConditionTrackers,
Yangster-mac94e197c2018-01-02 16:03:03 -080078 conditionIdIndexMap, stack);
Yao Chencaf339d2017-10-06 16:01:10 -070079
80 if (!initChildSucceeded) {
Yangster-mac94e197c2018-01-02 16:03:03 -080081 ALOGW("Child initialization failed %lld ", (long long)child);
Yao Chencaf339d2017-10-06 16:01:10 -070082 return false;
83 } else {
Tej Singhb7802512019-12-04 17:57:04 -080084 VLOG("Child initialization success %lld ", (long long)child);
Yao Chencaf339d2017-10-06 16:01:10 -070085 }
86
Yangster-mac93694462018-01-22 20:49:31 -080087 if (allConditionTrackers[childIndex]->isSliced()) {
88 setSliced(true);
Yangster13fb7e42018-03-07 17:30:49 -080089 mSlicedChildren.push_back(childIndex);
90 } else {
91 mUnSlicedChildren.push_back(childIndex);
Yangster-mac93694462018-01-22 20:49:31 -080092 }
Yao Chencaf339d2017-10-06 16:01:10 -070093 mChildren.push_back(childIndex);
Yao Chencaf339d2017-10-06 16:01:10 -070094 mTrackerIndex.insert(childTracker->getLogTrackerIndex().begin(),
95 childTracker->getLogTrackerIndex().end());
96 }
97
98 // unmark this node in the recursion stack.
99 stack[mIndex] = false;
100
101 mInitialized = true;
102
103 return true;
104}
105
Yao Chen729093d2017-10-16 10:33:26 -0700106void CombinationConditionTracker::isConditionMet(
Yao Chen8a8d16c2018-02-08 14:50:40 -0800107 const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
Yangster13fb7e42018-03-07 17:30:49 -0800108 const bool isPartialLink,
tsaichristine76853372019-08-06 17:17:03 -0700109 vector<ConditionState>& conditionCache) const {
Yangster-mac93694462018-01-22 20:49:31 -0800110 // So far, this is fine as there is at most one child having sliced output.
Yao Chen729093d2017-10-16 10:33:26 -0700111 for (const int childIndex : mChildren) {
112 if (conditionCache[childIndex] == ConditionState::kNotEvaluated) {
113 allConditions[childIndex]->isConditionMet(conditionParameters, allConditions,
Yangster13fb7e42018-03-07 17:30:49 -0800114 isPartialLink,
tsaichristine76853372019-08-06 17:17:03 -0700115 conditionCache);
Yao Chen729093d2017-10-16 10:33:26 -0700116 }
117 }
118 conditionCache[mIndex] =
119 evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache);
120}
121
Yao Chen967b2052017-11-07 16:36:43 -0800122void CombinationConditionTracker::evaluateCondition(
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700123 const LogEvent& event, const std::vector<MatchingState>& eventMatcherValues,
Yao Chencaf339d2017-10-06 16:01:10 -0700124 const std::vector<sp<ConditionTracker>>& mAllConditions,
Yao Chen729093d2017-10-16 10:33:26 -0700125 std::vector<ConditionState>& nonSlicedConditionCache,
Yao Chen967b2052017-11-07 16:36:43 -0800126 std::vector<bool>& conditionChangedCache) {
Yao Chencaf339d2017-10-06 16:01:10 -0700127 // value is up to date.
Yao Chen729093d2017-10-16 10:33:26 -0700128 if (nonSlicedConditionCache[mIndex] != ConditionState::kNotEvaluated) {
Yao Chen967b2052017-11-07 16:36:43 -0800129 return;
Yao Chencaf339d2017-10-06 16:01:10 -0700130 }
131
132 for (const int childIndex : mChildren) {
Yangster-mac93694462018-01-22 20:49:31 -0800133 // So far, this is fine as there is at most one child having sliced output.
Yao Chen729093d2017-10-16 10:33:26 -0700134 if (nonSlicedConditionCache[childIndex] == ConditionState::kNotEvaluated) {
Yao Chencaf339d2017-10-06 16:01:10 -0700135 const sp<ConditionTracker>& child = mAllConditions[childIndex];
Yao Chen729093d2017-10-16 10:33:26 -0700136 child->evaluateCondition(event, eventMatcherValues, mAllConditions,
Yao Chen967b2052017-11-07 16:36:43 -0800137 nonSlicedConditionCache, conditionChangedCache);
Yao Chencaf339d2017-10-06 16:01:10 -0700138 }
139 }
140
Yao Chen427d3722018-03-22 15:21:52 -0700141 ConditionState newCondition =
142 evaluateCombinationCondition(mChildren, mLogicalOperation, nonSlicedConditionCache);
Yao Chen967b2052017-11-07 16:36:43 -0800143 if (!mSliced) {
tsaichristinefe469732020-05-19 14:53:11 -0700144 bool nonSlicedChanged = (mUnSlicedPartCondition != newCondition);
145 mUnSlicedPartCondition = newCondition;
Yao Chencaf339d2017-10-06 16:01:10 -0700146
tsaichristinefe469732020-05-19 14:53:11 -0700147 nonSlicedConditionCache[mIndex] = mUnSlicedPartCondition;
Yao Chen967b2052017-11-07 16:36:43 -0800148 conditionChangedCache[mIndex] = nonSlicedChanged;
149 } else {
tsaichristinefe469732020-05-19 14:53:11 -0700150 mUnSlicedPartCondition = evaluateCombinationCondition(mUnSlicedChildren, mLogicalOperation,
151 nonSlicedConditionCache);
Yangster13fb7e42018-03-07 17:30:49 -0800152
Yao Chen729093d2017-10-16 10:33:26 -0700153 for (const int childIndex : mChildren) {
154 // If any of the sliced condition in children condition changes, the combination
155 // condition may be changed too.
Yao Chen967b2052017-11-07 16:36:43 -0800156 if (conditionChangedCache[childIndex]) {
157 conditionChangedCache[mIndex] = true;
Yao Chen729093d2017-10-16 10:33:26 -0700158 break;
159 }
160 }
Yao Chen427d3722018-03-22 15:21:52 -0700161 nonSlicedConditionCache[mIndex] = newCondition;
Yangster-mac86179502018-01-23 15:47:15 -0800162 VLOG("CombinationPredicate %lld sliced may changed? %d", (long long)mConditionId,
Yangster-mac94e197c2018-01-02 16:03:03 -0800163 conditionChangedCache[mIndex] == true);
Yao Chen729093d2017-10-16 10:33:26 -0700164 }
Yao Chencaf339d2017-10-06 16:01:10 -0700165}
166
Yangster13fb7e42018-03-07 17:30:49 -0800167bool CombinationConditionTracker::equalOutputDimensions(
168 const std::vector<sp<ConditionTracker>>& allConditions,
169 const vector<Matcher>& dimensions) const {
170 if (mSlicedChildren.size() != 1 ||
171 mSlicedChildren.front() >= (int)allConditions.size() ||
172 mLogicalOperation != LogicalOperation::AND) {
173 return false;
174 }
175 const sp<ConditionTracker>& slicedChild = allConditions.at(mSlicedChildren.front());
176 return slicedChild->equalOutputDimensions(allConditions, dimensions);
177}
178
Yao Chencaf339d2017-10-06 16:01:10 -0700179} // namespace statsd
180} // namespace os
181} // namespace android