blob: 624119f3ad045f40686dd302c22465bce1ed95f9 [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 */
16
Yao Chen5110bed2017-10-23 12:50:02 -070017#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
20#include "SimpleConditionTracker.h"
Yao Chenb3561512017-11-21 18:07:17 -080021#include "guardrail/StatsdStats.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070022
Yao Chencaf339d2017-10-06 16:01:10 -070023#include <log/logprint.h>
24
Joe Onorato9fc9edf2017-10-15 20:08:52 -070025namespace android {
26namespace os {
27namespace statsd {
28
Yao Chen729093d2017-10-16 10:33:26 -070029using std::map;
Yao Chencaf339d2017-10-06 16:01:10 -070030using std::string;
31using std::unique_ptr;
32using std::unordered_map;
33using std::vector;
34
Yao Chencaf339d2017-10-06 16:01:10 -070035SimpleConditionTracker::SimpleConditionTracker(
Yangster-mac94e197c2018-01-02 16:03:03 -080036 const ConfigKey& key, const int64_t& id, const int index,
Stefan Lafon12d01fa2017-12-04 20:56:09 -080037 const SimplePredicate& simplePredicate,
Yangster-mac94e197c2018-01-02 16:03:03 -080038 const unordered_map<int64_t, int>& trackerNameIndexMap)
39 : ConditionTracker(id, index), mConfigKey(key) {
40 VLOG("creating SimpleConditionTracker %lld", (long long)mConditionId);
Stefan Lafon12d01fa2017-12-04 20:56:09 -080041 mCountNesting = simplePredicate.count_nesting();
Yao Chencaf339d2017-10-06 16:01:10 -070042
Stefan Lafon12d01fa2017-12-04 20:56:09 -080043 if (simplePredicate.has_start()) {
44 auto pair = trackerNameIndexMap.find(simplePredicate.start());
Yao Chencaf339d2017-10-06 16:01:10 -070045 if (pair == trackerNameIndexMap.end()) {
Yangster-mac94e197c2018-01-02 16:03:03 -080046 ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start());
Yao Chencaf339d2017-10-06 16:01:10 -070047 return;
48 }
49 mStartLogMatcherIndex = pair->second;
50 mTrackerIndex.insert(mStartLogMatcherIndex);
51 } else {
52 mStartLogMatcherIndex = -1;
53 }
54
Stefan Lafon12d01fa2017-12-04 20:56:09 -080055 if (simplePredicate.has_stop()) {
56 auto pair = trackerNameIndexMap.find(simplePredicate.stop());
Yao Chencaf339d2017-10-06 16:01:10 -070057 if (pair == trackerNameIndexMap.end()) {
Yangster-mac94e197c2018-01-02 16:03:03 -080058 ALOGW("Stop matcher %lld not found in the config", (long long)simplePredicate.stop());
Yao Chencaf339d2017-10-06 16:01:10 -070059 return;
60 }
61 mStopLogMatcherIndex = pair->second;
Yao Chen4b146852017-10-10 15:34:42 -070062 mTrackerIndex.insert(mStopLogMatcherIndex);
Yao Chencaf339d2017-10-06 16:01:10 -070063 } else {
64 mStopLogMatcherIndex = -1;
65 }
66
Stefan Lafon12d01fa2017-12-04 20:56:09 -080067 if (simplePredicate.has_stop_all()) {
68 auto pair = trackerNameIndexMap.find(simplePredicate.stop_all());
Yao Chencaf339d2017-10-06 16:01:10 -070069 if (pair == trackerNameIndexMap.end()) {
Yangster-mac94e197c2018-01-02 16:03:03 -080070 ALOGW("Stop all matcher %lld found in the config", (long long)simplePredicate.stop_all());
Yao Chencaf339d2017-10-06 16:01:10 -070071 return;
72 }
73 mStopAllLogMatcherIndex = pair->second;
74 mTrackerIndex.insert(mStopAllLogMatcherIndex);
75 } else {
76 mStopAllLogMatcherIndex = -1;
77 }
78
Yao Chen8a8d16c2018-02-08 14:50:40 -080079 if (simplePredicate.has_dimensions()) {
80 translateFieldMatcher(simplePredicate.dimensions(), &mOutputDimensions);
81 if (mOutputDimensions.size() > 0) {
82 mSliced = true;
83 mDimensionTag = mOutputDimensions[0].mMatcher.getTag();
84 }
Yao Chen5154a3792017-10-30 22:57:06 -070085 }
86
Stefan Lafon12d01fa2017-12-04 20:56:09 -080087 if (simplePredicate.initial_value() == SimplePredicate_InitialValue_FALSE) {
Yao Chen967b2052017-11-07 16:36:43 -080088 mInitialValue = ConditionState::kFalse;
89 } else {
90 mInitialValue = ConditionState::kUnknown;
91 }
92
93 mNonSlicedConditionState = mInitialValue;
94
Yao Chencaf339d2017-10-06 16:01:10 -070095 mInitialized = true;
96}
97
98SimpleConditionTracker::~SimpleConditionTracker() {
99 VLOG("~SimpleConditionTracker()");
100}
101
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800102bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig,
Yao Chencaf339d2017-10-06 16:01:10 -0700103 const vector<sp<ConditionTracker>>& allConditionTrackers,
Yangster-mac94e197c2018-01-02 16:03:03 -0800104 const unordered_map<int64_t, int>& conditionIdIndexMap,
Yao Chencaf339d2017-10-06 16:01:10 -0700105 vector<bool>& stack) {
106 // SimpleConditionTracker does not have dependency on other conditions, thus we just return
107 // if the initialization was successful.
108 return mInitialized;
109}
110
Yao Chen8a8d16c2018-02-08 14:50:40 -0800111void print(const map<HashableDimensionKey, int>& conditions, const int64_t& id) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800112 VLOG("%lld DUMP:", (long long)id);
Yao Chen729093d2017-10-16 10:33:26 -0700113 for (const auto& pair : conditions) {
Yao Chen967b2052017-11-07 16:36:43 -0800114 VLOG("\t%s : %d", pair.first.c_str(), pair.second);
Yao Chen729093d2017-10-16 10:33:26 -0700115 }
116}
117
Yao Chen967b2052017-11-07 16:36:43 -0800118void SimpleConditionTracker::handleStopAll(std::vector<ConditionState>& conditionCache,
119 std::vector<bool>& conditionChangedCache) {
120 // Unless the default condition is false, and there was nothing started, otherwise we have
121 // triggered a condition change.
122 conditionChangedCache[mIndex] =
123 (mInitialValue == ConditionState::kFalse && mSlicedConditionState.empty()) ? false
124 : true;
125
126 // After StopAll, we know everything has stopped. From now on, default condition is false.
127 mInitialValue = ConditionState::kFalse;
128 mSlicedConditionState.clear();
129 conditionCache[mIndex] = ConditionState::kFalse;
130}
131
Yao Chenb3561512017-11-21 18:07:17 -0800132bool SimpleConditionTracker::hitGuardRail(const HashableDimensionKey& newKey) {
133 if (!mSliced || mSlicedConditionState.find(newKey) != mSlicedConditionState.end()) {
134 // if the condition is not sliced or the key is not new, we are good!
135 return false;
136 }
137 // 1. Report the tuple count if the tuple count > soft limit
138 if (mSlicedConditionState.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
139 size_t newTupleCount = mSlicedConditionState.size() + 1;
Yangster-mac94e197c2018-01-02 16:03:03 -0800140 StatsdStats::getInstance().noteConditionDimensionSize(mConfigKey, mConditionId, newTupleCount);
Yao Chenb3561512017-11-21 18:07:17 -0800141 // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
142 if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800143 ALOGE("Predicate %lld dropping data for dimension key %s",
144 (long long)mConditionId, newKey.c_str());
Yao Chenb3561512017-11-21 18:07:17 -0800145 return true;
146 }
147 }
148 return false;
149}
150
Yao Chen967b2052017-11-07 16:36:43 -0800151void SimpleConditionTracker::handleConditionEvent(const HashableDimensionKey& outputKey,
Yao Chen8a8d16c2018-02-08 14:50:40 -0800152 bool matchStart, ConditionState* conditionCache,
153 bool* conditionChangedCache) {
Yao Chen967b2052017-11-07 16:36:43 -0800154 bool changed = false;
155 auto outputIt = mSlicedConditionState.find(outputKey);
156 ConditionState newCondition;
Yao Chenb3561512017-11-21 18:07:17 -0800157 if (hitGuardRail(outputKey)) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800158 (*conditionChangedCache) = false;
Yao Chenb3561512017-11-21 18:07:17 -0800159 // Tells the caller it's evaluated.
Yao Chen8a8d16c2018-02-08 14:50:40 -0800160 (*conditionCache) = ConditionState::kUnknown;
Yao Chenb3561512017-11-21 18:07:17 -0800161 return;
162 }
Yao Chen967b2052017-11-07 16:36:43 -0800163 if (outputIt == mSlicedConditionState.end()) {
164 // We get a new output key.
165 newCondition = matchStart ? ConditionState::kTrue : ConditionState::kFalse;
166 if (matchStart && mInitialValue != ConditionState::kTrue) {
Yangster-mac5503f5c2018-01-15 23:20:44 -0800167 mSlicedConditionState.insert(std::make_pair(outputKey, 1));
Yao Chen967b2052017-11-07 16:36:43 -0800168 changed = true;
169 } else if (mInitialValue != ConditionState::kFalse) {
170 // it's a stop and we don't have history about it.
171 // If the default condition is not false, it means this stop is valuable to us.
Yangster-mac5503f5c2018-01-15 23:20:44 -0800172 mSlicedConditionState.insert(std::make_pair(outputKey, 0));
Yao Chen967b2052017-11-07 16:36:43 -0800173 changed = true;
174 }
175 } else {
176 // we have history about this output key.
177 auto& startedCount = outputIt->second;
178 // assign the old value first.
179 newCondition = startedCount > 0 ? ConditionState::kTrue : ConditionState::kFalse;
180 if (matchStart) {
181 if (startedCount == 0) {
182 // This condition for this output key will change from false -> true
183 changed = true;
184 }
185
186 // it's ok to do ++ here, even if we don't count nesting. The >1 counts will be treated
187 // as 1 if not counting nesting.
188 startedCount++;
189 newCondition = ConditionState::kTrue;
190 } else {
191 // This is a stop event.
192 if (startedCount > 0) {
193 if (mCountNesting) {
194 startedCount--;
195 if (startedCount == 0) {
196 newCondition = ConditionState::kFalse;
197 }
198 } else {
199 // not counting nesting, so ignore the number of starts, stop now.
200 startedCount = 0;
201 newCondition = ConditionState::kFalse;
202 }
203 // if everything has stopped for this output key, condition true -> false;
204 if (startedCount == 0) {
205 changed = true;
206 }
207 }
208
209 // if default condition is false, it means we don't need to keep the false values.
210 if (mInitialValue == ConditionState::kFalse && startedCount == 0) {
211 mSlicedConditionState.erase(outputIt);
212 VLOG("erase key %s", outputKey.c_str());
213 }
214 }
215 }
216
217 // dump all dimensions for debugging
218 if (DEBUG) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800219 print(mSlicedConditionState, mConditionId);
Yao Chen967b2052017-11-07 16:36:43 -0800220 }
221
Yao Chen8a8d16c2018-02-08 14:50:40 -0800222 (*conditionChangedCache) = changed;
223 (*conditionCache) = newCondition;
Yangster-mac94e197c2018-01-02 16:03:03 -0800224 VLOG("SimplePredicate %lld nonSlicedChange? %d", (long long)mConditionId,
Yao Chen967b2052017-11-07 16:36:43 -0800225 conditionChangedCache[mIndex] == true);
226}
227
Yangster-mac93694462018-01-22 20:49:31 -0800228void SimpleConditionTracker::evaluateCondition(
229 const LogEvent& event,
230 const vector<MatchingState>& eventMatcherValues,
231 const vector<sp<ConditionTracker>>& mAllConditions,
232 vector<ConditionState>& conditionCache,
233 vector<bool>& conditionChangedCache) {
Yao Chencaf339d2017-10-06 16:01:10 -0700234 if (conditionCache[mIndex] != ConditionState::kNotEvaluated) {
235 // it has been evaluated.
Yangster-mac94e197c2018-01-02 16:03:03 -0800236 VLOG("Yes, already evaluated, %lld %d",
237 (long long)mConditionId, conditionCache[mIndex]);
Yao Chen967b2052017-11-07 16:36:43 -0800238 return;
Yao Chencaf339d2017-10-06 16:01:10 -0700239 }
240
David Chenc18abed2017-11-22 16:47:59 -0800241 if (mStopAllLogMatcherIndex >= 0 && mStopAllLogMatcherIndex < int(eventMatcherValues.size()) &&
Yao Chen967b2052017-11-07 16:36:43 -0800242 eventMatcherValues[mStopAllLogMatcherIndex] == MatchingState::kMatched) {
243 handleStopAll(conditionCache, conditionChangedCache);
244 return;
245 }
Yao Chen729093d2017-10-16 10:33:26 -0700246
Yao Chen967b2052017-11-07 16:36:43 -0800247 int matchedState = -1;
Yao Chencaf339d2017-10-06 16:01:10 -0700248 // Note: The order to evaluate the following start, stop, stop_all matters.
249 // The priority of overwrite is stop_all > stop > start.
250 if (mStartLogMatcherIndex >= 0 &&
251 eventMatcherValues[mStartLogMatcherIndex] == MatchingState::kMatched) {
Yao Chen967b2052017-11-07 16:36:43 -0800252 matchedState = 1;
Yao Chencaf339d2017-10-06 16:01:10 -0700253 }
254
255 if (mStopLogMatcherIndex >= 0 &&
256 eventMatcherValues[mStopLogMatcherIndex] == MatchingState::kMatched) {
Yao Chen967b2052017-11-07 16:36:43 -0800257 matchedState = 0;
Yao Chencaf339d2017-10-06 16:01:10 -0700258 }
259
Yao Chen967b2052017-11-07 16:36:43 -0800260 if (matchedState < 0) {
Yao Chend41c4222017-11-15 19:26:14 -0800261 // The event doesn't match this condition. So we just report existing condition values.
Yao Chen967b2052017-11-07 16:36:43 -0800262 conditionChangedCache[mIndex] = false;
Yao Chend41c4222017-11-15 19:26:14 -0800263 if (mSliced) {
264 // if the condition result is sliced. metrics won't directly get value from the
265 // cache, so just set any value other than kNotEvaluated.
Yangster-mac93694462018-01-22 20:49:31 -0800266 conditionCache[mIndex] = mInitialValue;
Yao Chend41c4222017-11-15 19:26:14 -0800267 } else {
Yangster7c334a12017-11-22 14:24:24 -0800268 const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY);
269 if (itr == mSlicedConditionState.end()) {
270 // condition not sliced, but we haven't seen the matched start or stop yet. so
271 // return initial value.
272 conditionCache[mIndex] = mInitialValue;
273 } else {
274 // return the cached condition.
275 conditionCache[mIndex] =
276 itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
277 }
Yao Chend41c4222017-11-15 19:26:14 -0800278 }
Yangster7c334a12017-11-22 14:24:24 -0800279
Yao Chen967b2052017-11-07 16:36:43 -0800280 return;
Yao Chen729093d2017-10-16 10:33:26 -0700281 }
282
Yao Chen8a8d16c2018-02-08 14:50:40 -0800283 ConditionState overallState = mInitialValue;
284 bool overallChanged = false;
285
286 if (mOutputDimensions.size() == 0) {
287 handleConditionEvent(DEFAULT_DIMENSION_KEY, matchedState == 1, &overallState,
288 &overallChanged);
Yangster-mac20877162017-12-22 17:19:39 -0800289 } else {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800290 std::vector<HashableDimensionKey> outputValues;
291 filterValues(mOutputDimensions, event.getValues(), &outputValues);
292
Yangster-mac20877162017-12-22 17:19:39 -0800293 // If this event has multiple nodes in the attribution chain, this log event probably will
294 // generate multiple dimensions. If so, we will find if the condition changes for any
295 // dimension and ask the corresponding metric producer to verify whether the actual sliced
296 // condition has changed or not.
297 // A high level assumption is that a predicate is either sliced or unsliced. We will never
298 // have both sliced and unsliced version of a predicate.
Yao Chen8a8d16c2018-02-08 14:50:40 -0800299 for (const HashableDimensionKey& outputValue : outputValues) {
300 // For sliced conditions, the value in the cache is not used. We don't need to update
301 // the overall condition state.
302 ConditionState tempState = ConditionState::kUnknown;
303 bool tempChanged = false;
304 handleConditionEvent(outputValue, matchedState == 1, &tempState, &tempChanged);
305 if (tempChanged) {
306 overallChanged = true;
307 }
Yangster-mac20877162017-12-22 17:19:39 -0800308 }
309 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800310 conditionCache[mIndex] = overallState;
311 conditionChangedCache[mIndex] = overallChanged;
Yao Chen729093d2017-10-16 10:33:26 -0700312}
313
314void SimpleConditionTracker::isConditionMet(
Yao Chen8a8d16c2018-02-08 14:50:40 -0800315 const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
316 const vector<Matcher>& dimensionFields, vector<ConditionState>& conditionCache,
317 std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
318
Yangster-mac93694462018-01-22 20:49:31 -0800319 if (conditionCache[mIndex] != ConditionState::kNotEvaluated) {
320 // it has been evaluated.
321 VLOG("Yes, already evaluated, %lld %d",
322 (long long)mConditionId, conditionCache[mIndex]);
Yao Chen729093d2017-10-16 10:33:26 -0700323 return;
324 }
Yangster-mac93694462018-01-22 20:49:31 -0800325 const auto pair = conditionParameters.find(mConditionId);
326
327 if (pair == conditionParameters.end()) {
328 ConditionState conditionState = ConditionState::kNotEvaluated;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800329 if (dimensionFields.size() > 0 && dimensionFields[0].mMatcher.getTag() == mDimensionTag) {
Yangster-mac93694462018-01-22 20:49:31 -0800330 conditionState = conditionState | getMetConditionDimension(
331 allConditions, dimensionFields, dimensionsKeySet);
332 } else {
333 conditionState = conditionState | mInitialValue;
334 if (!mSliced) {
335 const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY);
336 if (itr != mSlicedConditionState.end()) {
337 ConditionState sliceState =
338 itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
339 conditionState = conditionState | sliceState;
340 }
341 }
342 }
343 conditionCache[mIndex] = conditionState;
344 return;
345 }
346 std::vector<HashableDimensionKey> defaultKeys = { DEFAULT_DIMENSION_KEY };
Yangster-mac20877162017-12-22 17:19:39 -0800347 const std::vector<HashableDimensionKey> &keys =
348 (pair == conditionParameters.end()) ? defaultKeys : pair->second;
Yao Chen729093d2017-10-16 10:33:26 -0700349
Yangster-mac20877162017-12-22 17:19:39 -0800350 ConditionState conditionState = ConditionState::kNotEvaluated;
Yangster-mac93694462018-01-22 20:49:31 -0800351 for (size_t i = 0; i < keys.size(); ++i) {
352 const HashableDimensionKey& key = keys[i];
Yangster-mac20877162017-12-22 17:19:39 -0800353 auto startedCountIt = mSlicedConditionState.find(key);
354 if (startedCountIt != mSlicedConditionState.end()) {
Yangster-mac93694462018-01-22 20:49:31 -0800355 ConditionState sliceState =
356 startedCountIt->second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
357 conditionState = conditionState | sliceState;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800358 if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) {
359 vector<HashableDimensionKey> dimensionKeys;
360 filterValues(dimensionFields, startedCountIt->first.getValues(), &dimensionKeys);
361 dimensionsKeySet.insert(dimensionKeys.begin(), dimensionKeys.end());
Yangster-mac93694462018-01-22 20:49:31 -0800362 }
Yangster-mac20877162017-12-22 17:19:39 -0800363 } else {
Yangster-mac5503f5c2018-01-15 23:20:44 -0800364 // For unseen key, check whether the require dimensions are subset of sliced condition
365 // output.
Yangster-mac93694462018-01-22 20:49:31 -0800366 conditionState = conditionState | mInitialValue;
Yangster-mac5503f5c2018-01-15 23:20:44 -0800367 for (const auto& slice : mSlicedConditionState) {
Yangster-mac93694462018-01-22 20:49:31 -0800368 ConditionState sliceState =
369 slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800370 if (slice.first.contains(key)) {
Yangster-mac93694462018-01-22 20:49:31 -0800371 conditionState = conditionState | sliceState;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800372 if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) {
373 vector<HashableDimensionKey> dimensionKeys;
374 filterValues(dimensionFields, slice.first.getValues(), &dimensionKeys);
375
376 dimensionsKeySet.insert(dimensionKeys.begin(), dimensionKeys.end());
377 }
Yangster-mac93694462018-01-22 20:49:31 -0800378 }
Yangster-mac5503f5c2018-01-15 23:20:44 -0800379 }
Yangster-mac5503f5c2018-01-15 23:20:44 -0800380 }
Yangster-mac20877162017-12-22 17:19:39 -0800381 }
Yangster-mac20877162017-12-22 17:19:39 -0800382 conditionCache[mIndex] = conditionState;
Yangster-mac94e197c2018-01-02 16:03:03 -0800383 VLOG("Predicate %lld return %d", (long long)mConditionId, conditionCache[mIndex]);
Yao Chencaf339d2017-10-06 16:01:10 -0700384}
385
Yangster-mac93694462018-01-22 20:49:31 -0800386ConditionState SimpleConditionTracker::getMetConditionDimension(
387 const std::vector<sp<ConditionTracker>>& allConditions,
Yao Chen8a8d16c2018-02-08 14:50:40 -0800388 const vector<Matcher>& dimensionFields,
389 std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const {
Yangster-mac93694462018-01-22 20:49:31 -0800390 ConditionState conditionState = mInitialValue;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800391 if (dimensionFields.size() == 0 || mOutputDimensions.size() == 0 ||
392 dimensionFields[0].mMatcher.getTag() != mOutputDimensions[0].mMatcher.getTag()) {
Yangster-mac93694462018-01-22 20:49:31 -0800393 const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY);
394 if (itr != mSlicedConditionState.end()) {
395 ConditionState sliceState =
396 itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
397 conditionState = conditionState | sliceState;
398 }
399 return conditionState;
400 }
401
402 for (const auto& slice : mSlicedConditionState) {
403 ConditionState sliceState =
404 slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
Yangster-mac93694462018-01-22 20:49:31 -0800405 conditionState = conditionState | sliceState;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800406
407 if (sliceState == ConditionState::kTrue && dimensionFields.size() > 0) {
408 vector<HashableDimensionKey> dimensionKeys;
409 filterValues(dimensionFields, slice.first.getValues(), &dimensionKeys);
410
411 dimensionsKeySet.insert(dimensionKeys.begin(), dimensionKeys.end());
Yangster-mac93694462018-01-22 20:49:31 -0800412 }
413 }
414 return conditionState;
415}
416
Yao Chencaf339d2017-10-06 16:01:10 -0700417} // namespace statsd
418} // namespace os
419} // namespace android