blob: 25265d5dabd746729326f047b674630f1bda2b09 [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"
Yangster-mac5503f5c2018-01-15 23:20:44 -080022#include "dimension.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070023
Yao Chencaf339d2017-10-06 16:01:10 -070024#include <log/logprint.h>
25
Joe Onorato9fc9edf2017-10-15 20:08:52 -070026namespace android {
27namespace os {
28namespace statsd {
29
Yao Chen729093d2017-10-16 10:33:26 -070030using std::map;
Yao Chencaf339d2017-10-06 16:01:10 -070031using std::string;
32using std::unique_ptr;
33using std::unordered_map;
34using std::vector;
35
Yao Chencaf339d2017-10-06 16:01:10 -070036SimpleConditionTracker::SimpleConditionTracker(
Yangster-mac94e197c2018-01-02 16:03:03 -080037 const ConfigKey& key, const int64_t& id, const int index,
Stefan Lafon12d01fa2017-12-04 20:56:09 -080038 const SimplePredicate& simplePredicate,
Yangster-mac94e197c2018-01-02 16:03:03 -080039 const unordered_map<int64_t, int>& trackerNameIndexMap)
40 : ConditionTracker(id, index), mConfigKey(key) {
41 VLOG("creating SimpleConditionTracker %lld", (long long)mConditionId);
Stefan Lafon12d01fa2017-12-04 20:56:09 -080042 mCountNesting = simplePredicate.count_nesting();
Yao Chencaf339d2017-10-06 16:01:10 -070043
Stefan Lafon12d01fa2017-12-04 20:56:09 -080044 if (simplePredicate.has_start()) {
45 auto pair = trackerNameIndexMap.find(simplePredicate.start());
Yao Chencaf339d2017-10-06 16:01:10 -070046 if (pair == trackerNameIndexMap.end()) {
Yangster-mac94e197c2018-01-02 16:03:03 -080047 ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start());
Yao Chencaf339d2017-10-06 16:01:10 -070048 return;
49 }
50 mStartLogMatcherIndex = pair->second;
51 mTrackerIndex.insert(mStartLogMatcherIndex);
52 } else {
53 mStartLogMatcherIndex = -1;
54 }
55
Stefan Lafon12d01fa2017-12-04 20:56:09 -080056 if (simplePredicate.has_stop()) {
57 auto pair = trackerNameIndexMap.find(simplePredicate.stop());
Yao Chencaf339d2017-10-06 16:01:10 -070058 if (pair == trackerNameIndexMap.end()) {
Yangster-mac94e197c2018-01-02 16:03:03 -080059 ALOGW("Stop matcher %lld not found in the config", (long long)simplePredicate.stop());
Yao Chencaf339d2017-10-06 16:01:10 -070060 return;
61 }
62 mStopLogMatcherIndex = pair->second;
Yao Chen4b146852017-10-10 15:34:42 -070063 mTrackerIndex.insert(mStopLogMatcherIndex);
Yao Chencaf339d2017-10-06 16:01:10 -070064 } else {
65 mStopLogMatcherIndex = -1;
66 }
67
Stefan Lafon12d01fa2017-12-04 20:56:09 -080068 if (simplePredicate.has_stop_all()) {
69 auto pair = trackerNameIndexMap.find(simplePredicate.stop_all());
Yao Chencaf339d2017-10-06 16:01:10 -070070 if (pair == trackerNameIndexMap.end()) {
Yangster-mac94e197c2018-01-02 16:03:03 -080071 ALOGW("Stop all matcher %lld found in the config", (long long)simplePredicate.stop_all());
Yao Chencaf339d2017-10-06 16:01:10 -070072 return;
73 }
74 mStopAllLogMatcherIndex = pair->second;
75 mTrackerIndex.insert(mStopAllLogMatcherIndex);
76 } else {
77 mStopAllLogMatcherIndex = -1;
78 }
79
Yangster-mac20877162017-12-22 17:19:39 -080080 mOutputDimensions = simplePredicate.dimensions();
Yao Chen5154a3792017-10-30 22:57:06 -070081
Yangster-mac20877162017-12-22 17:19:39 -080082 if (mOutputDimensions.child_size() > 0) {
Yao Chen5154a3792017-10-30 22:57:06 -070083 mSliced = true;
84 }
85
Stefan Lafon12d01fa2017-12-04 20:56:09 -080086 if (simplePredicate.initial_value() == SimplePredicate_InitialValue_FALSE) {
Yao Chen967b2052017-11-07 16:36:43 -080087 mInitialValue = ConditionState::kFalse;
88 } else {
89 mInitialValue = ConditionState::kUnknown;
90 }
91
92 mNonSlicedConditionState = mInitialValue;
93
Yao Chencaf339d2017-10-06 16:01:10 -070094 mInitialized = true;
95}
96
97SimpleConditionTracker::~SimpleConditionTracker() {
98 VLOG("~SimpleConditionTracker()");
99}
100
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800101bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig,
Yao Chencaf339d2017-10-06 16:01:10 -0700102 const vector<sp<ConditionTracker>>& allConditionTrackers,
Yangster-mac94e197c2018-01-02 16:03:03 -0800103 const unordered_map<int64_t, int>& conditionIdIndexMap,
Yao Chencaf339d2017-10-06 16:01:10 -0700104 vector<bool>& stack) {
105 // SimpleConditionTracker does not have dependency on other conditions, thus we just return
106 // if the initialization was successful.
Yangster-mac93694462018-01-22 20:49:31 -0800107 if (mOutputDimensions.has_field() || mOutputDimensions.child_size() > 0) {
108 setSliced(true);
109 }
Yao Chencaf339d2017-10-06 16:01:10 -0700110 return mInitialized;
111}
112
Yangster-mac94e197c2018-01-02 16:03:03 -0800113void print(map<HashableDimensionKey, int>& conditions, const int64_t& id) {
114 VLOG("%lld DUMP:", (long long)id);
Yao Chen729093d2017-10-16 10:33:26 -0700115 for (const auto& pair : conditions) {
Yao Chen967b2052017-11-07 16:36:43 -0800116 VLOG("\t%s : %d", pair.first.c_str(), pair.second);
Yao Chen729093d2017-10-16 10:33:26 -0700117 }
118}
119
Yao Chen967b2052017-11-07 16:36:43 -0800120void SimpleConditionTracker::handleStopAll(std::vector<ConditionState>& conditionCache,
121 std::vector<bool>& conditionChangedCache) {
122 // Unless the default condition is false, and there was nothing started, otherwise we have
123 // triggered a condition change.
124 conditionChangedCache[mIndex] =
125 (mInitialValue == ConditionState::kFalse && mSlicedConditionState.empty()) ? false
126 : true;
127
128 // After StopAll, we know everything has stopped. From now on, default condition is false.
129 mInitialValue = ConditionState::kFalse;
130 mSlicedConditionState.clear();
131 conditionCache[mIndex] = ConditionState::kFalse;
132}
133
Yao Chenb3561512017-11-21 18:07:17 -0800134bool SimpleConditionTracker::hitGuardRail(const HashableDimensionKey& newKey) {
135 if (!mSliced || mSlicedConditionState.find(newKey) != mSlicedConditionState.end()) {
136 // if the condition is not sliced or the key is not new, we are good!
137 return false;
138 }
139 // 1. Report the tuple count if the tuple count > soft limit
140 if (mSlicedConditionState.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
141 size_t newTupleCount = mSlicedConditionState.size() + 1;
Yangster-mac94e197c2018-01-02 16:03:03 -0800142 StatsdStats::getInstance().noteConditionDimensionSize(mConfigKey, mConditionId, newTupleCount);
Yao Chenb3561512017-11-21 18:07:17 -0800143 // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
144 if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800145 ALOGE("Predicate %lld dropping data for dimension key %s",
146 (long long)mConditionId, newKey.c_str());
Yao Chenb3561512017-11-21 18:07:17 -0800147 return true;
148 }
149 }
150 return false;
151}
152
Yao Chen967b2052017-11-07 16:36:43 -0800153void SimpleConditionTracker::handleConditionEvent(const HashableDimensionKey& outputKey,
154 bool matchStart,
155 std::vector<ConditionState>& conditionCache,
156 std::vector<bool>& conditionChangedCache) {
Yangster-mac20877162017-12-22 17:19:39 -0800157 if ((int)conditionChangedCache.size() <= mIndex) {
158 ALOGE("handleConditionEvent: param conditionChangedCache not initialized.");
159 return;
160 }
161 if ((int)conditionCache.size() <= mIndex) {
162 ALOGE("handleConditionEvent: param conditionCache not initialized.");
163 return;
164 }
Yao Chen967b2052017-11-07 16:36:43 -0800165 bool changed = false;
166 auto outputIt = mSlicedConditionState.find(outputKey);
167 ConditionState newCondition;
Yao Chenb3561512017-11-21 18:07:17 -0800168 if (hitGuardRail(outputKey)) {
169 conditionChangedCache[mIndex] = false;
170 // Tells the caller it's evaluated.
171 conditionCache[mIndex] = ConditionState::kUnknown;
172 return;
173 }
Yao Chen967b2052017-11-07 16:36:43 -0800174 if (outputIt == mSlicedConditionState.end()) {
175 // We get a new output key.
176 newCondition = matchStart ? ConditionState::kTrue : ConditionState::kFalse;
177 if (matchStart && mInitialValue != ConditionState::kTrue) {
Yangster-mac5503f5c2018-01-15 23:20:44 -0800178 mSlicedConditionState.insert(std::make_pair(outputKey, 1));
Yao Chen967b2052017-11-07 16:36:43 -0800179 changed = true;
180 } else if (mInitialValue != ConditionState::kFalse) {
181 // it's a stop and we don't have history about it.
182 // If the default condition is not false, it means this stop is valuable to us.
Yangster-mac5503f5c2018-01-15 23:20:44 -0800183 mSlicedConditionState.insert(std::make_pair(outputKey, 0));
Yao Chen967b2052017-11-07 16:36:43 -0800184 changed = true;
185 }
186 } else {
187 // we have history about this output key.
188 auto& startedCount = outputIt->second;
189 // assign the old value first.
190 newCondition = startedCount > 0 ? ConditionState::kTrue : ConditionState::kFalse;
191 if (matchStart) {
192 if (startedCount == 0) {
193 // This condition for this output key will change from false -> true
194 changed = true;
195 }
196
197 // it's ok to do ++ here, even if we don't count nesting. The >1 counts will be treated
198 // as 1 if not counting nesting.
199 startedCount++;
200 newCondition = ConditionState::kTrue;
201 } else {
202 // This is a stop event.
203 if (startedCount > 0) {
204 if (mCountNesting) {
205 startedCount--;
206 if (startedCount == 0) {
207 newCondition = ConditionState::kFalse;
208 }
209 } else {
210 // not counting nesting, so ignore the number of starts, stop now.
211 startedCount = 0;
212 newCondition = ConditionState::kFalse;
213 }
214 // if everything has stopped for this output key, condition true -> false;
215 if (startedCount == 0) {
216 changed = true;
217 }
218 }
219
220 // if default condition is false, it means we don't need to keep the false values.
221 if (mInitialValue == ConditionState::kFalse && startedCount == 0) {
222 mSlicedConditionState.erase(outputIt);
223 VLOG("erase key %s", outputKey.c_str());
224 }
225 }
226 }
227
228 // dump all dimensions for debugging
229 if (DEBUG) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800230 print(mSlicedConditionState, mConditionId);
Yao Chen967b2052017-11-07 16:36:43 -0800231 }
232
233 conditionChangedCache[mIndex] = changed;
234 conditionCache[mIndex] = newCondition;
235
Yangster-mac94e197c2018-01-02 16:03:03 -0800236 VLOG("SimplePredicate %lld nonSlicedChange? %d", (long long)mConditionId,
Yao Chen967b2052017-11-07 16:36:43 -0800237 conditionChangedCache[mIndex] == true);
238}
239
Yangster-mac93694462018-01-22 20:49:31 -0800240void SimpleConditionTracker::evaluateCondition(
241 const LogEvent& event,
242 const vector<MatchingState>& eventMatcherValues,
243 const vector<sp<ConditionTracker>>& mAllConditions,
244 vector<ConditionState>& conditionCache,
245 vector<bool>& conditionChangedCache) {
Yao Chencaf339d2017-10-06 16:01:10 -0700246 if (conditionCache[mIndex] != ConditionState::kNotEvaluated) {
247 // it has been evaluated.
Yangster-mac94e197c2018-01-02 16:03:03 -0800248 VLOG("Yes, already evaluated, %lld %d",
249 (long long)mConditionId, conditionCache[mIndex]);
Yao Chen967b2052017-11-07 16:36:43 -0800250 return;
Yao Chencaf339d2017-10-06 16:01:10 -0700251 }
252
David Chenc18abed2017-11-22 16:47:59 -0800253 if (mStopAllLogMatcherIndex >= 0 && mStopAllLogMatcherIndex < int(eventMatcherValues.size()) &&
Yao Chen967b2052017-11-07 16:36:43 -0800254 eventMatcherValues[mStopAllLogMatcherIndex] == MatchingState::kMatched) {
255 handleStopAll(conditionCache, conditionChangedCache);
256 return;
257 }
Yao Chen729093d2017-10-16 10:33:26 -0700258
Yao Chen967b2052017-11-07 16:36:43 -0800259 int matchedState = -1;
Yao Chencaf339d2017-10-06 16:01:10 -0700260 // Note: The order to evaluate the following start, stop, stop_all matters.
261 // The priority of overwrite is stop_all > stop > start.
262 if (mStartLogMatcherIndex >= 0 &&
263 eventMatcherValues[mStartLogMatcherIndex] == MatchingState::kMatched) {
Yao Chen967b2052017-11-07 16:36:43 -0800264 matchedState = 1;
Yao Chencaf339d2017-10-06 16:01:10 -0700265 }
266
267 if (mStopLogMatcherIndex >= 0 &&
268 eventMatcherValues[mStopLogMatcherIndex] == MatchingState::kMatched) {
Yao Chen967b2052017-11-07 16:36:43 -0800269 matchedState = 0;
Yao Chencaf339d2017-10-06 16:01:10 -0700270 }
271
Yao Chen967b2052017-11-07 16:36:43 -0800272 if (matchedState < 0) {
Yao Chend41c4222017-11-15 19:26:14 -0800273 // The event doesn't match this condition. So we just report existing condition values.
Yao Chen967b2052017-11-07 16:36:43 -0800274 conditionChangedCache[mIndex] = false;
Yao Chend41c4222017-11-15 19:26:14 -0800275 if (mSliced) {
276 // if the condition result is sliced. metrics won't directly get value from the
277 // cache, so just set any value other than kNotEvaluated.
Yangster-mac93694462018-01-22 20:49:31 -0800278 conditionCache[mIndex] = mInitialValue;
Yao Chend41c4222017-11-15 19:26:14 -0800279 } else {
Yangster7c334a12017-11-22 14:24:24 -0800280 const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY);
281 if (itr == mSlicedConditionState.end()) {
282 // condition not sliced, but we haven't seen the matched start or stop yet. so
283 // return initial value.
284 conditionCache[mIndex] = mInitialValue;
285 } else {
286 // return the cached condition.
287 conditionCache[mIndex] =
288 itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
289 }
Yao Chend41c4222017-11-15 19:26:14 -0800290 }
Yangster7c334a12017-11-22 14:24:24 -0800291
Yao Chen967b2052017-11-07 16:36:43 -0800292 return;
Yao Chen729093d2017-10-16 10:33:26 -0700293 }
294
Yangster-mac20877162017-12-22 17:19:39 -0800295 // outputKey is the output values. e.g, uid:1234
Yangster-mac7ba8fc32018-01-24 16:16:46 -0800296 std::vector<DimensionsValue> outputValues;
297 getDimensionKeys(event, mOutputDimensions, &outputValues);
Yangster-mac20877162017-12-22 17:19:39 -0800298 if (outputValues.size() == 0) {
299 // The original implementation would generate an empty string dimension hash when condition
300 // is not sliced.
301 handleConditionEvent(
302 DEFAULT_DIMENSION_KEY, matchedState == 1, conditionCache, conditionChangedCache);
303 } else if (outputValues.size() == 1) {
304 handleConditionEvent(HashableDimensionKey(outputValues[0]), matchedState == 1,
305 conditionCache, conditionChangedCache);
306 } else {
307 // If this event has multiple nodes in the attribution chain, this log event probably will
308 // generate multiple dimensions. If so, we will find if the condition changes for any
309 // dimension and ask the corresponding metric producer to verify whether the actual sliced
310 // condition has changed or not.
311 // A high level assumption is that a predicate is either sliced or unsliced. We will never
312 // have both sliced and unsliced version of a predicate.
313 for (const DimensionsValue& outputValue : outputValues) {
314 vector<ConditionState> dimensionalConditionCache(conditionCache.size(),
315 ConditionState::kNotEvaluated);
316 vector<bool> dimensionalConditionChangedCache(conditionChangedCache.size(), false);
Yangster-mac20877162017-12-22 17:19:39 -0800317 handleConditionEvent(HashableDimensionKey(outputValue), matchedState == 1,
318 dimensionalConditionCache, dimensionalConditionChangedCache);
Yangster-mac20877162017-12-22 17:19:39 -0800319 OrConditionState(dimensionalConditionCache, &conditionCache);
320 OrBooleanVector(dimensionalConditionChangedCache, &conditionChangedCache);
321 }
322 }
Yao Chen729093d2017-10-16 10:33:26 -0700323}
324
325void SimpleConditionTracker::isConditionMet(
Yangster-mac20877162017-12-22 17:19:39 -0800326 const ConditionKey& conditionParameters,
Yangster7c334a12017-11-22 14:24:24 -0800327 const vector<sp<ConditionTracker>>& allConditions,
Yangster-mac93694462018-01-22 20:49:31 -0800328 const FieldMatcher& dimensionFields,
329 vector<ConditionState>& conditionCache,
330 std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const {
331 if (conditionCache[mIndex] != ConditionState::kNotEvaluated) {
332 // it has been evaluated.
333 VLOG("Yes, already evaluated, %lld %d",
334 (long long)mConditionId, conditionCache[mIndex]);
Yao Chen729093d2017-10-16 10:33:26 -0700335 return;
336 }
Yangster-mac93694462018-01-22 20:49:31 -0800337 const auto pair = conditionParameters.find(mConditionId);
338
339 if (pair == conditionParameters.end()) {
340 ConditionState conditionState = ConditionState::kNotEvaluated;
341 if (dimensionFields.has_field() && dimensionFields.child_size() > 0 &&
342 dimensionFields.field() == mOutputDimensions.field()) {
343 conditionState = conditionState | getMetConditionDimension(
344 allConditions, dimensionFields, dimensionsKeySet);
345 } else {
346 conditionState = conditionState | mInitialValue;
347 if (!mSliced) {
348 const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY);
349 if (itr != mSlicedConditionState.end()) {
350 ConditionState sliceState =
351 itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
352 conditionState = conditionState | sliceState;
353 }
354 }
355 }
356 conditionCache[mIndex] = conditionState;
357 return;
358 }
359 std::vector<HashableDimensionKey> defaultKeys = { DEFAULT_DIMENSION_KEY };
Yangster-mac20877162017-12-22 17:19:39 -0800360 const std::vector<HashableDimensionKey> &keys =
361 (pair == conditionParameters.end()) ? defaultKeys : pair->second;
Yao Chen729093d2017-10-16 10:33:26 -0700362
Yangster-mac20877162017-12-22 17:19:39 -0800363 ConditionState conditionState = ConditionState::kNotEvaluated;
Yangster-mac93694462018-01-22 20:49:31 -0800364 for (size_t i = 0; i < keys.size(); ++i) {
365 const HashableDimensionKey& key = keys[i];
Yangster-mac20877162017-12-22 17:19:39 -0800366 auto startedCountIt = mSlicedConditionState.find(key);
367 if (startedCountIt != mSlicedConditionState.end()) {
Yangster-mac93694462018-01-22 20:49:31 -0800368 ConditionState sliceState =
369 startedCountIt->second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
370 conditionState = conditionState | sliceState;
371 if (sliceState == ConditionState::kTrue && dimensionFields.has_field()) {
372 HashableDimensionKey dimensionKey;
373 if (getSubDimension(startedCountIt->first.getDimensionsValue(), dimensionFields,
374 dimensionKey.getMutableDimensionsValue())) {
375 dimensionsKeySet.insert(dimensionKey);
376 }
377 }
Yangster-mac20877162017-12-22 17:19:39 -0800378 } else {
Yangster-mac5503f5c2018-01-15 23:20:44 -0800379 // For unseen key, check whether the require dimensions are subset of sliced condition
380 // output.
Yangster-mac93694462018-01-22 20:49:31 -0800381 conditionState = conditionState | mInitialValue;
Yangster-mac5503f5c2018-01-15 23:20:44 -0800382 for (const auto& slice : mSlicedConditionState) {
Yangster-mac93694462018-01-22 20:49:31 -0800383 ConditionState sliceState =
384 slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
385 if (IsSubDimension(slice.first.getDimensionsValue(), key.getDimensionsValue())) {
386 conditionState = conditionState | sliceState;
387 if (sliceState == ConditionState::kTrue && dimensionFields.has_field()) {
388 HashableDimensionKey dimensionKey;
389 if (getSubDimension(slice.first.getDimensionsValue(),
390 dimensionFields, dimensionKey.getMutableDimensionsValue())) {
391 dimensionsKeySet.insert(dimensionKey);
392 }
393 }
Yangster-mac5503f5c2018-01-15 23:20:44 -0800394 }
Yangster-mac5503f5c2018-01-15 23:20:44 -0800395 }
Yangster-mac20877162017-12-22 17:19:39 -0800396 }
Yao Chen729093d2017-10-16 10:33:26 -0700397 }
Yangster-mac20877162017-12-22 17:19:39 -0800398 conditionCache[mIndex] = conditionState;
Yangster-mac94e197c2018-01-02 16:03:03 -0800399 VLOG("Predicate %lld return %d", (long long)mConditionId, conditionCache[mIndex]);
Yao Chencaf339d2017-10-06 16:01:10 -0700400}
401
Yangster-mac93694462018-01-22 20:49:31 -0800402ConditionState SimpleConditionTracker::getMetConditionDimension(
403 const std::vector<sp<ConditionTracker>>& allConditions,
404 const FieldMatcher& dimensionFields,
405 std::unordered_set<HashableDimensionKey> &dimensionsKeySet) const {
406 ConditionState conditionState = mInitialValue;
407 if (!dimensionFields.has_field() ||
408 !mOutputDimensions.has_field() ||
409 dimensionFields.field() != mOutputDimensions.field()) {
410 const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY);
411 if (itr != mSlicedConditionState.end()) {
412 ConditionState sliceState =
413 itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
414 conditionState = conditionState | sliceState;
415 }
416 return conditionState;
417 }
418
419 for (const auto& slice : mSlicedConditionState) {
420 ConditionState sliceState =
421 slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse;
422 DimensionsValue dimensionsValue;
423 conditionState = conditionState | sliceState;
424 HashableDimensionKey dimensionKey;
425 if (sliceState == ConditionState::kTrue &&
426 getSubDimension(slice.first.getDimensionsValue(), dimensionFields,
427 dimensionKey.getMutableDimensionsValue())) {
428 dimensionsKeySet.insert(dimensionKey);
429 }
430 }
431 return conditionState;
432}
433
Yao Chencaf339d2017-10-06 16:01:10 -0700434} // namespace statsd
435} // namespace os
436} // namespace android