blob: 8869241ab8aa3402060845b9916588d2b612c427 [file] [log] [blame]
Yao Chen729093d2017-10-16 10:33:26 -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 Chen3c0b95c2017-12-16 14:34:20 -080017#define DEBUG false
Yao Chen5154a3792017-10-30 22:57:06 -070018
Yao Chen729093d2017-10-16 10:33:26 -070019#include "Log.h"
Tej Singhcfa32e12020-10-15 03:14:19 -070020
Yao Chen5154a3792017-10-30 22:57:06 -070021#include "DurationMetricProducer.h"
Yao Chen729093d2017-10-16 10:33:26 -070022
Yao Chen729093d2017-10-16 10:33:26 -070023#include <limits.h>
24#include <stdlib.h>
25
Tej Singhcfa32e12020-10-15 03:14:19 -070026#include "guardrail/StatsdStats.h"
27#include "metrics/parsing_utils/metrics_manager_util.h"
28#include "stats_log_util.h"
29#include "stats_util.h"
30
yrob0378b02017-11-09 20:36:25 -080031using android::util::FIELD_COUNT_REPEATED;
yro2b0f8862017-11-06 14:27:31 -080032using android::util::FIELD_TYPE_BOOL;
33using android::util::FIELD_TYPE_FLOAT;
34using android::util::FIELD_TYPE_INT32;
35using android::util::FIELD_TYPE_INT64;
36using android::util::FIELD_TYPE_MESSAGE;
Yangster-macd1815dc2017-11-13 21:43:15 -080037using android::util::FIELD_TYPE_STRING;
yro2b0f8862017-11-06 14:27:31 -080038using android::util::ProtoOutputStream;
Yao Chen729093d2017-10-16 10:33:26 -070039using std::string;
40using std::unordered_map;
41using std::vector;
Ruchir Rastogi21a287b2019-10-02 12:04:33 -070042using std::shared_ptr;
Yao Chen729093d2017-10-16 10:33:26 -070043
44namespace android {
45namespace os {
46namespace statsd {
47
yro2b0f8862017-11-06 14:27:31 -080048// for StatsLogReport
Yangster-mac94e197c2018-01-02 16:03:03 -080049const int FIELD_ID_ID = 1;
yro2b0f8862017-11-06 14:27:31 -080050const int FIELD_ID_DURATION_METRICS = 6;
Yangster-mac9def8e32018-04-17 13:55:51 -070051const int FIELD_ID_TIME_BASE = 9;
52const int FIELD_ID_BUCKET_SIZE = 10;
53const int FIELD_ID_DIMENSION_PATH_IN_WHAT = 11;
Howard Ro9440e092018-12-16 19:15:21 -080054const int FIELD_ID_IS_ACTIVE = 14;
yro2b0f8862017-11-06 14:27:31 -080055// for DurationMetricDataWrapper
56const int FIELD_ID_DATA = 1;
57// for DurationMetricData
Yangster-mac468ff042018-01-17 12:26:34 -080058const int FIELD_ID_DIMENSION_IN_WHAT = 1;
Yangster-mac468ff042018-01-17 12:26:34 -080059const int FIELD_ID_BUCKET_INFO = 3;
Yangster-mac9def8e32018-04-17 13:55:51 -070060const int FIELD_ID_DIMENSION_LEAF_IN_WHAT = 4;
tsaichristine1449fa42020-01-02 12:12:05 -080061const int FIELD_ID_SLICE_BY_STATE = 6;
yro2b0f8862017-11-06 14:27:31 -080062// for DurationBucketInfo
yro2b0f8862017-11-06 14:27:31 -080063const int FIELD_ID_DURATION = 3;
Yangster-mac9def8e32018-04-17 13:55:51 -070064const int FIELD_ID_BUCKET_NUM = 4;
65const int FIELD_ID_START_BUCKET_ELAPSED_MILLIS = 5;
66const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;
yro2b0f8862017-11-06 14:27:31 -080067
Ruchir Rastogi21a287b2019-10-02 12:04:33 -070068DurationMetricProducer::DurationMetricProducer(
69 const ConfigKey& key, const DurationMetric& metric, const int conditionIndex,
Tej Singhcfa32e12020-10-15 03:14:19 -070070 const vector<ConditionState>& initialConditionCache, const int startIndex,
71 const int stopIndex, const int stopAllIndex, const bool nesting,
Tej Singh052d11c2020-08-28 02:48:40 -070072 const sp<ConditionWizard>& wizard, const uint64_t protoHash,
73 const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs,
Ruchir Rastogi21a287b2019-10-02 12:04:33 -070074 const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
tsaichristined21aacf2019-10-07 14:47:38 -070075 const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
76 const vector<int>& slicedStateAtoms,
77 const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
tsaichristine6e2e92d2020-05-18 14:39:45 -070078 : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, wizard,
Tej Singh052d11c2020-08-28 02:48:40 -070079 protoHash, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
80 stateGroupMap),
Yao Chenf09569f2017-12-13 17:00:51 -080081 mAggregationType(metric.aggregation_type()),
Yao Chen729093d2017-10-16 10:33:26 -070082 mStartIndex(startIndex),
83 mStopIndex(stopIndex),
Yao Chen5154a3792017-10-30 22:57:06 -070084 mStopAllIndex(stopAllIndex),
Yangster13fb7e42018-03-07 17:30:49 -080085 mNested(nesting),
86 mContainANYPositionInInternalDimensions(false) {
Yangster-macb8144812018-01-04 10:56:23 -080087 if (metric.has_bucket()) {
yro59cc24d2018-02-13 20:17:32 -080088 mBucketSizeNs =
89 TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000;
Yao Chen729093d2017-10-16 10:33:26 -070090 } else {
91 mBucketSizeNs = LLONG_MAX;
92 }
93
Yao Chen8a8d16c2018-02-08 14:50:40 -080094 if (metric.has_dimensions_in_what()) {
95 translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat);
Yangster13fb7e42018-03-07 17:30:49 -080096 mContainANYPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what());
Yao Chen8a8d16c2018-02-08 14:50:40 -080097 }
98
99 if (internalDimensions.has_field()) {
100 translateFieldMatcher(internalDimensions, &mInternalDimensions);
Yangster13fb7e42018-03-07 17:30:49 -0800101 mContainANYPositionInInternalDimensions = HasPositionANY(internalDimensions);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800102 }
Yangster-mace06cfd72018-03-10 23:22:59 -0800103 if (mContainANYPositionInInternalDimensions) {
104 ALOGE("Position ANY in internal dimension not supported.");
105 }
106 if (mContainANYPositionInDimensionsInWhat) {
107 ALOGE("Position ANY in dimension_in_what not supported.");
108 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800109
tsaichristine76853372019-08-06 17:17:03 -0700110 mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what());
Yangster-mac9def8e32018-04-17 13:55:51 -0700111
Yao Chen729093d2017-10-16 10:33:26 -0700112 if (metric.links().size() > 0) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800113 for (const auto& link : metric.links()) {
114 Metric2Condition mc;
115 mc.conditionId = link.condition();
116 translateFieldMatcher(link.fields_in_what(), &mc.metricFields);
117 translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields);
118 mMetric2ConditionLinks.push_back(mc);
119 }
tsaichristine76853372019-08-06 17:17:03 -0700120 mConditionSliced = true;
Yao Chen729093d2017-10-16 10:33:26 -0700121 }
Yangster13fb7e42018-03-07 17:30:49 -0800122 mUnSlicedPartCondition = ConditionState::kUnknown;
Yao Chen729093d2017-10-16 10:33:26 -0700123
tsaichristine1449fa42020-01-02 12:12:05 -0800124 for (const auto& stateLink : metric.state_link()) {
125 Metric2State ms;
126 ms.stateAtomId = stateLink.state_atom_id();
127 translateFieldMatcher(stateLink.fields_in_what(), &ms.metricFields);
128 translateFieldMatcher(stateLink.fields_in_state(), &ms.stateFields);
129 mMetric2StateLinks.push_back(ms);
130 }
131
Yangster13fb7e42018-03-07 17:30:49 -0800132 mUseWhatDimensionAsInternalDimension = equalDimensions(mDimensionsInWhat, mInternalDimensions);
tsaichristine76853372019-08-06 17:17:03 -0700133 if (mWizard != nullptr && mConditionTrackerIndex >= 0 &&
134 mMetric2ConditionLinks.size() == 1) {
tsaichristine69000e62019-10-18 17:34:52 -0700135 mHasLinksToAllConditionDimensionsInTracker = mWizard->equalOutputDimensions(
136 mConditionTrackerIndex, mMetric2ConditionLinks.begin()->conditionFields);
Yangster-mac53928882018-02-25 23:02:56 -0800137 }
Chenjie Yue1361ed2018-07-23 17:33:09 -0700138 flushIfNeededLocked(startTimeNs);
139 // Adjust start for partial bucket
140 mCurrentBucketStartTimeNs = startTimeNs;
Yangster-mac94e197c2018-01-02 16:03:03 -0800141 VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700142 (long long)mBucketSizeNs, (long long)mTimeBaseNs);
Yao Chen729093d2017-10-16 10:33:26 -0700143}
144
145DurationMetricProducer::~DurationMetricProducer() {
146 VLOG("~DurationMetric() called");
147}
148
Tej Singhcfa32e12020-10-15 03:14:19 -0700149bool DurationMetricProducer::onConfigUpdatedLocked(
150 const StatsdConfig& config, const int configIndex, const int metricIndex,
151 const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
152 const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
153 const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
154 const sp<EventMatcherWizard>& matcherWizard,
155 const vector<sp<ConditionTracker>>& allConditionTrackers,
156 const unordered_map<int64_t, int>& conditionTrackerMap, const sp<ConditionWizard>& wizard,
157 const unordered_map<int64_t, int>& metricToActivationMap,
158 unordered_map<int, vector<int>>& trackerToMetricMap,
159 unordered_map<int, vector<int>>& conditionToMetricMap,
160 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
161 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
162 vector<int>& metricsWithActivation) {
163 if (!MetricProducer::onConfigUpdatedLocked(
164 config, configIndex, metricIndex, allAtomMatchingTrackers,
165 oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
166 allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
167 trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
168 deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
169 return false;
170 }
171
172 const DurationMetric& metric = config.duration_metric(configIndex);
173 const auto& what_it = conditionTrackerMap.find(metric.what());
174 if (what_it == conditionTrackerMap.end()) {
175 ALOGE("DurationMetric's \"what\" is not present in the config");
176 return false;
177 }
178
179 const Predicate& durationWhat = config.predicate(what_it->second);
180 if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
181 ALOGE("DurationMetric's \"what\" must be a simple condition");
182 return false;
183 }
184
185 const SimplePredicate& simplePredicate = durationWhat.simple_predicate();
186
187 // Update indices: mStartIndex, mStopIndex, mStopAllIndex, mConditionIndex and MetricsManager
188 // maps.
189 if (!handleMetricWithAtomMatchingTrackers(simplePredicate.start(), metricIndex,
190 metric.has_dimensions_in_what(),
191 allAtomMatchingTrackers, newAtomMatchingTrackerMap,
192 trackerToMetricMap, mStartIndex)) {
193 ALOGE("Duration metrics must specify a valid start event matcher");
194 return false;
195 }
196
197 if (simplePredicate.has_stop() &&
198 !handleMetricWithAtomMatchingTrackers(simplePredicate.stop(), metricIndex,
199 metric.has_dimensions_in_what(),
200 allAtomMatchingTrackers, newAtomMatchingTrackerMap,
201 trackerToMetricMap, mStopIndex)) {
202 return false;
203 }
204
205 if (simplePredicate.has_stop_all() &&
206 !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex,
207 metric.has_dimensions_in_what(),
208 allAtomMatchingTrackers, newAtomMatchingTrackerMap,
209 trackerToMetricMap, mStopAllIndex)) {
210 return false;
211 }
212
213 if (metric.has_condition() &&
214 !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
215 metric.links(), allConditionTrackers, mConditionTrackerIndex,
216 conditionToMetricMap)) {
217 return false;
218 }
219
220 for (const auto& it : mCurrentSlicedDurationTrackerMap) {
221 it.second->onConfigUpdated(wizard, mConditionTrackerIndex);
222 }
223
224 return true;
225}
226
Yangster-mac932ecec2018-02-01 10:23:52 -0800227sp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker(
228 const Alert &alert, const sp<AlarmMonitor>& anomalyAlarmMonitor) {
Bookatz857aaa52017-12-19 15:29:06 -0800229 std::lock_guard<std::mutex> lock(mMutex);
Bookatz423f7532018-03-08 15:45:14 -0800230 if (mAggregationType == DurationMetric_AggregationType_SUM) {
231 if (alert.trigger_if_sum_gt() > alert.num_buckets() * mBucketSizeNs) {
232 ALOGW("invalid alert for SUM: threshold (%f) > possible recordable value (%d x %lld)",
233 alert.trigger_if_sum_gt(), alert.num_buckets(), (long long)mBucketSizeNs);
234 return nullptr;
235 }
236 }
Tej Singhd07d0ff2020-10-27 20:56:11 -0700237 sp<AnomalyTracker> anomalyTracker =
238 new DurationAnomalyTracker(alert, mConfigKey, anomalyAlarmMonitor);
239 addAnomalyTrackerLocked(anomalyTracker);
Bookatz857aaa52017-12-19 15:29:06 -0800240 return anomalyTracker;
Bookatz450099d2017-11-30 17:09:30 -0800241}
242
Tej Singhd07d0ff2020-10-27 20:56:11 -0700243// Adds an AnomalyTracker that has already been created.
244// Note: this gets called on config updates, and will only get called if the metric and the
245// associated alert are preserved, which means the AnomalyTracker must be a DurationAnomalyTracker.
246void DurationMetricProducer::addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker) {
247 std::lock_guard<std::mutex> lock(mMutex);
248 addAnomalyTrackerLocked(anomalyTracker);
249}
250
251void DurationMetricProducer::addAnomalyTrackerLocked(sp<AnomalyTracker>& anomalyTracker) {
252 mAnomalyTrackers.push_back(anomalyTracker);
253 for (const auto& [_, durationTracker] : mCurrentSlicedDurationTrackerMap) {
254 durationTracker->addAnomalyTracker(anomalyTracker);
255 }
256}
tsaichristine1449fa42020-01-02 12:12:05 -0800257void DurationMetricProducer::onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
258 const HashableDimensionKey& primaryKey,
tsaichristine9f951052020-05-13 14:32:37 -0700259 const FieldValue& oldState,
260 const FieldValue& newState) {
tsaichristine1449fa42020-01-02 12:12:05 -0800261 // Check if this metric has a StateMap. If so, map the new state value to
262 // the correct state group id.
tsaichristine9f951052020-05-13 14:32:37 -0700263 FieldValue newStateCopy = newState;
264 mapStateValue(atomId, &newStateCopy);
tsaichristine1449fa42020-01-02 12:12:05 -0800265
266 flushIfNeededLocked(eventTimeNs);
267
268 // Each duration tracker is mapped to a different whatKey (a set of values from the
269 // dimensionsInWhat fields). We notify all trackers iff the primaryKey field values from the
270 // state change event are a subset of the tracker's whatKey field values.
271 //
272 // Ex. For a duration metric dimensioned on uid and tag:
273 // DurationTracker1 whatKey = uid: 1001, tag: 1
274 // DurationTracker2 whatKey = uid: 1002, tag 1
275 //
276 // If the state change primaryKey = uid: 1001, we only notify DurationTracker1 of a state
277 // change.
278 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
279 if (!containsLinkedStateValues(whatIt.first, primaryKey, mMetric2StateLinks, atomId)) {
280 continue;
281 }
tsaichristine9f951052020-05-13 14:32:37 -0700282 whatIt.second->onStateChanged(eventTimeNs, atomId, newStateCopy);
tsaichristine1449fa42020-01-02 12:12:05 -0800283 }
284}
285
Yao Chen5154a3792017-10-30 22:57:06 -0700286unique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker(
Yangster-mac93694462018-01-22 20:49:31 -0800287 const MetricDimensionKey& eventKey) const {
Yao Chenf09569f2017-12-13 17:00:51 -0800288 switch (mAggregationType) {
Stefan Lafoncfed20b2017-11-18 09:26:53 -0800289 case DurationMetric_AggregationType_SUM:
Yao Chenb3561512017-11-21 18:07:17 -0800290 return make_unique<OringDurationTracker>(
tsaichristine1449fa42020-01-02 12:12:05 -0800291 mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested,
292 mCurrentBucketStartTimeNs, mCurrentBucketNum, mTimeBaseNs, mBucketSizeNs,
293 mConditionSliced, mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
Stefan Lafoncfed20b2017-11-18 09:26:53 -0800294 case DurationMetric_AggregationType_MAX_SPARSE:
Yao Chenb3561512017-11-21 18:07:17 -0800295 return make_unique<MaxDurationTracker>(
tsaichristine1449fa42020-01-02 12:12:05 -0800296 mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested,
297 mCurrentBucketStartTimeNs, mCurrentBucketNum, mTimeBaseNs, mBucketSizeNs,
298 mConditionSliced, mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
Yangster13fb7e42018-03-07 17:30:49 -0800299 }
300}
301
302// SlicedConditionChange optimization case 1:
303// 1. If combination condition, logical operation is AND, only one sliced child predicate.
tsaichristine76853372019-08-06 17:17:03 -0700304// 2. The links covers all dimension fields in the sliced child condition predicate.
Yao Chen427d3722018-03-22 15:21:52 -0700305void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(bool condition,
Yangster-macb142cc82018-03-30 15:22:08 -0700306 const int64_t eventTime) {
Yangster13fb7e42018-03-07 17:30:49 -0800307 if (mMetric2ConditionLinks.size() != 1 ||
tsaichristine76853372019-08-06 17:17:03 -0700308 !mHasLinksToAllConditionDimensionsInTracker) {
Yangster13fb7e42018-03-07 17:30:49 -0800309 return;
310 }
311
312 bool currentUnSlicedPartCondition = true;
313 if (!mWizard->IsSimpleCondition(mConditionTrackerIndex)) {
314 ConditionState unslicedPartState =
315 mWizard->getUnSlicedPartConditionState(mConditionTrackerIndex);
316 // When the unsliced part is still false, return directly.
317 if (mUnSlicedPartCondition == ConditionState::kFalse &&
318 unslicedPartState == ConditionState::kFalse) {
319 return;
320 }
321 mUnSlicedPartCondition = unslicedPartState;
322 currentUnSlicedPartCondition = mUnSlicedPartCondition > 0;
323 }
324
325 auto dimensionsChangedToTrue = mWizard->getChangedToTrueDimensions(mConditionTrackerIndex);
326 auto dimensionsChangedToFalse = mWizard->getChangedToFalseDimensions(mConditionTrackerIndex);
327
328 // The condition change is from the unsliced predicates.
329 // We need to find out the true dimensions from the sliced predicate and flip their condition
330 // state based on the new unsliced condition state.
331 if (dimensionsChangedToTrue == nullptr || dimensionsChangedToFalse == nullptr ||
332 (dimensionsChangedToTrue->empty() && dimensionsChangedToFalse->empty())) {
333 std::set<HashableDimensionKey> trueConditionDimensions;
334 mWizard->getTrueSlicedDimensions(mConditionTrackerIndex, &trueConditionDimensions);
335 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
336 HashableDimensionKey linkedConditionDimensionKey;
tsaichristine69000e62019-10-18 17:34:52 -0700337 getDimensionForCondition(whatIt.first.getValues(), mMetric2ConditionLinks[0],
Yangster13fb7e42018-03-07 17:30:49 -0800338 &linkedConditionDimensionKey);
339 if (trueConditionDimensions.find(linkedConditionDimensionKey) !=
340 trueConditionDimensions.end()) {
tsaichristine81899f12020-01-08 12:42:12 -0800341 whatIt.second->onConditionChanged(currentUnSlicedPartCondition, eventTime);
Yangster13fb7e42018-03-07 17:30:49 -0800342 }
343 }
344 } else {
345 // Handle the condition change from the sliced predicate.
346 if (currentUnSlicedPartCondition) {
347 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
348 HashableDimensionKey linkedConditionDimensionKey;
tsaichristine69000e62019-10-18 17:34:52 -0700349 getDimensionForCondition(whatIt.first.getValues(), mMetric2ConditionLinks[0],
Yangster13fb7e42018-03-07 17:30:49 -0800350 &linkedConditionDimensionKey);
351 if (dimensionsChangedToTrue->find(linkedConditionDimensionKey) !=
352 dimensionsChangedToTrue->end()) {
tsaichristine81899f12020-01-08 12:42:12 -0800353 whatIt.second->onConditionChanged(true, eventTime);
Yangster13fb7e42018-03-07 17:30:49 -0800354 }
355 if (dimensionsChangedToFalse->find(linkedConditionDimensionKey) !=
356 dimensionsChangedToFalse->end()) {
tsaichristine81899f12020-01-08 12:42:12 -0800357 whatIt.second->onConditionChanged(false, eventTime);
Yangster13fb7e42018-03-07 17:30:49 -0800358 }
359 }
360 }
361 }
362}
363
Muhammad Qureshi18e46922019-05-24 16:38:49 -0700364void DurationMetricProducer::onSlicedConditionMayChangeInternalLocked(bool overallCondition,
365 const int64_t eventTimeNs) {
Yangster13fb7e42018-03-07 17:30:49 -0800366 bool changeDimTrackable = mWizard->IsChangedDimensionTrackable(mConditionTrackerIndex);
tsaichristine76853372019-08-06 17:17:03 -0700367 if (changeDimTrackable && mHasLinksToAllConditionDimensionsInTracker) {
Muhammad Qureshi18e46922019-05-24 16:38:49 -0700368 onSlicedConditionMayChangeLocked_opt1(overallCondition, eventTimeNs);
Yangster13fb7e42018-03-07 17:30:49 -0800369 return;
370 }
371
Yao Chen729093d2017-10-16 10:33:26 -0700372 // Now for each of the on-going event, check if the condition has changed for them.
Yangster-mac53928882018-02-25 23:02:56 -0800373 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
tsaichristine81899f12020-01-08 12:42:12 -0800374 whatIt.second->onSlicedConditionMayChange(overallCondition, eventTimeNs);
Yao Chen729093d2017-10-16 10:33:26 -0700375 }
376}
377
Muhammad Qureshi18e46922019-05-24 16:38:49 -0700378void DurationMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
379 const int64_t eventTime) {
380 VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
381
382 if (!mIsActive) {
383 return;
384 }
385
386 flushIfNeededLocked(eventTime);
387
388 if (!mConditionSliced) {
389 return;
390 }
391
392 onSlicedConditionMayChangeInternalLocked(overallCondition, eventTime);
393}
394
395void DurationMetricProducer::onActiveStateChangedLocked(const int64_t& eventTimeNs) {
396 MetricProducer::onActiveStateChangedLocked(eventTimeNs);
397
398 if (!mConditionSliced) {
399 if (ConditionState::kTrue != mCondition) {
400 return;
401 }
402
403 if (mIsActive) {
404 flushIfNeededLocked(eventTimeNs);
405 }
406
407 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
tsaichristine81899f12020-01-08 12:42:12 -0800408 whatIt.second->onConditionChanged(mIsActive, eventTimeNs);
Muhammad Qureshi18e46922019-05-24 16:38:49 -0700409 }
410 } else if (mIsActive) {
411 flushIfNeededLocked(eventTimeNs);
412 onSlicedConditionMayChangeInternalLocked(mIsActive, eventTimeNs);
413 } else { // mConditionSliced == true && !mIsActive
414 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
tsaichristine81899f12020-01-08 12:42:12 -0800415 whatIt.second->onConditionChanged(mIsActive, eventTimeNs);
Muhammad Qureshi18e46922019-05-24 16:38:49 -0700416 }
417 }
418}
419
Yangsterf2bee6f2017-11-29 12:01:05 -0800420void DurationMetricProducer::onConditionChangedLocked(const bool conditionMet,
Yangster-macb142cc82018-03-30 15:22:08 -0700421 const int64_t eventTime) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800422 VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
Olivier Gaillarde63d9e02019-02-12 14:43:59 +0000423 mCondition = conditionMet ? ConditionState::kTrue : ConditionState::kFalse;
Muhammad Qureshi18e46922019-05-24 16:38:49 -0700424
425 if (!mIsActive) {
426 return;
427 }
428
Yangsterf2bee6f2017-11-29 12:01:05 -0800429 flushIfNeededLocked(eventTime);
Yangster-mac53928882018-02-25 23:02:56 -0800430 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
tsaichristine81899f12020-01-08 12:42:12 -0800431 whatIt.second->onConditionChanged(conditionMet, eventTime);
Yao Chen729093d2017-10-16 10:33:26 -0700432 }
433}
434
Yangster-macb142cc82018-03-30 15:22:08 -0700435void DurationMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
Yao Chen06dba5d2018-01-26 13:38:16 -0800436 flushIfNeededLocked(dropTimeNs);
Olivier Gaillard320952b2019-02-06 13:57:24 +0000437 StatsdStats::getInstance().noteBucketDropped(mMetricId);
Yao Chen06dba5d2018-01-26 13:38:16 -0800438 mPastBuckets.clear();
439}
440
Yangster-maca802d732018-04-24 07:50:38 -0700441void DurationMetricProducer::clearPastBucketsLocked(const int64_t dumpTimeNs) {
442 flushIfNeededLocked(dumpTimeNs);
443 mPastBuckets.clear();
444}
445
Yangster-macb142cc82018-03-30 15:22:08 -0700446void DurationMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
Yangster-mace68f3a52018-04-04 00:01:43 -0700447 const bool include_current_partial_bucket,
Bookatzff71cad2018-09-20 17:17:49 -0700448 const bool erase_data,
Olivier Gaillard6c75ecd2019-02-20 09:57:33 +0000449 const DumpLatency dumpLatency,
Yangster-mac9def8e32018-04-17 13:55:51 -0700450 std::set<string> *str_set,
Yao Chen288c6002017-12-12 13:43:18 -0800451 ProtoOutputStream* protoOutput) {
Yangster-mace68f3a52018-04-04 00:01:43 -0700452 if (include_current_partial_bucket) {
453 flushLocked(dumpTimeNs);
454 } else {
455 flushIfNeededLocked(dumpTimeNs);
456 }
Yang Lub4722912018-11-15 11:02:03 -0800457 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
Howard Ro07e23ff2018-12-17 17:28:07 -0800458 protoOutput->write(FIELD_TYPE_BOOL | FIELD_ID_IS_ACTIVE, isActiveLocked());
Yang Lub4722912018-11-15 11:02:03 -0800459
Yangster-mac635b4b32018-01-23 20:17:35 -0800460 if (mPastBuckets.empty()) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800461 VLOG(" Duration metric, empty return");
Yangster-mac635b4b32018-01-23 20:17:35 -0800462 return;
463 }
Yao Chen6a8c7992017-11-29 20:02:07 +0000464
Yangster-mac9def8e32018-04-17 13:55:51 -0700465 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TIME_BASE, (long long)mTimeBaseNs);
466 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_SIZE, (long long)mBucketSizeNs);
467
468 if (!mSliceByPositionALL) {
469 if (!mDimensionsInWhat.empty()) {
470 uint64_t dimenPathToken = protoOutput->start(
471 FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_WHAT);
472 writeDimensionPathToProto(mDimensionsInWhat, protoOutput);
473 protoOutput->end(dimenPathToken);
474 }
Yangster-mac9def8e32018-04-17 13:55:51 -0700475 }
476
Yi Jin5ee07872018-03-05 18:18:27 -0800477 uint64_t protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DURATION_METRICS);
Yao Chen288c6002017-12-12 13:43:18 -0800478
Yao Chen8a8d16c2018-02-08 14:50:40 -0800479 VLOG("Duration metric %lld dump report now...", (long long)mMetricId);
Yao Chen6a8c7992017-11-29 20:02:07 +0000480
Yao Chen729093d2017-10-16 10:33:26 -0700481 for (const auto& pair : mPastBuckets) {
Yangster-mac93694462018-01-22 20:49:31 -0800482 const MetricDimensionKey& dimensionKey = pair.first;
Yangster13fb7e42018-03-07 17:30:49 -0800483 VLOG(" dimension key %s", dimensionKey.toString().c_str());
Yao Chen1ff4f432017-11-16 17:01:40 -0800484
Yi Jin5ee07872018-03-05 18:18:27 -0800485 uint64_t wrapperToken =
Yao Chen288c6002017-12-12 13:43:18 -0800486 protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
yro2b0f8862017-11-06 14:27:31 -0800487
Yangster-mac20877162017-12-22 17:19:39 -0800488 // First fill dimension.
Yangster-mac9def8e32018-04-17 13:55:51 -0700489 if (mSliceByPositionALL) {
490 uint64_t dimensionToken = protoOutput->start(
491 FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
492 writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), str_set, protoOutput);
493 protoOutput->end(dimensionToken);
Yangster-mac9def8e32018-04-17 13:55:51 -0700494 } else {
495 writeDimensionLeafNodesToProto(dimensionKey.getDimensionKeyInWhat(),
496 FIELD_ID_DIMENSION_LEAF_IN_WHAT, str_set, protoOutput);
Yangster-mac93694462018-01-22 20:49:31 -0800497 }
tsaichristine1449fa42020-01-02 12:12:05 -0800498 // Then fill slice_by_state.
499 for (auto state : dimensionKey.getStateValuesKey().getValues()) {
500 uint64_t stateToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
501 FIELD_ID_SLICE_BY_STATE);
502 writeStateToProto(state, protoOutput);
503 protoOutput->end(stateToken);
504 }
yro2b0f8862017-11-06 14:27:31 -0800505 // Then fill bucket_info (DurationBucketInfo).
506 for (const auto& bucket : pair.second) {
Yi Jin5ee07872018-03-05 18:18:27 -0800507 uint64_t bucketInfoToken = protoOutput->start(
Yao Chen288c6002017-12-12 13:43:18 -0800508 FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO);
Yangster-mac9def8e32018-04-17 13:55:51 -0700509 if (bucket.mBucketEndNs - bucket.mBucketStartNs != mBucketSizeNs) {
510 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_ELAPSED_MILLIS,
511 (long long)NanoToMillis(bucket.mBucketStartNs));
512 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_ELAPSED_MILLIS,
513 (long long)NanoToMillis(bucket.mBucketEndNs));
514 } else {
515 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_NUM,
516 (long long)(getBucketNumFromEndTimeNs(bucket.mBucketEndNs)));
517 }
Yao Chen288c6002017-12-12 13:43:18 -0800518 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DURATION, (long long)bucket.mDuration);
519 protoOutput->end(bucketInfoToken);
yro2b0f8862017-11-06 14:27:31 -0800520 VLOG("\t bucket [%lld - %lld] duration: %lld", (long long)bucket.mBucketStartNs,
521 (long long)bucket.mBucketEndNs, (long long)bucket.mDuration);
522 }
523
Yao Chen288c6002017-12-12 13:43:18 -0800524 protoOutput->end(wrapperToken);
Yao Chen729093d2017-10-16 10:33:26 -0700525 }
yro2b0f8862017-11-06 14:27:31 -0800526
Yao Chen288c6002017-12-12 13:43:18 -0800527 protoOutput->end(protoToken);
Bookatzff71cad2018-09-20 17:17:49 -0700528 if (erase_data) {
529 mPastBuckets.clear();
530 }
yro2b0f8862017-11-06 14:27:31 -0800531}
Yao Chen729093d2017-10-16 10:33:26 -0700532
Yangster-macb142cc82018-03-30 15:22:08 -0700533void DurationMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
534 int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
David Chen27785a82018-01-19 17:06:45 -0800535
536 if (currentBucketEndTimeNs > eventTimeNs) {
Yao Chen729093d2017-10-16 10:33:26 -0700537 return;
538 }
Yao Chen5154a3792017-10-30 22:57:06 -0700539 VLOG("flushing...........");
David Chen27785a82018-01-19 17:06:45 -0800540 int numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
Muhammad Qureshi902529a2019-03-14 16:03:21 -0700541 int64_t nextBucketNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
542 flushCurrentBucketLocked(eventTimeNs, nextBucketNs);
543
Yangster-mace2cd6d52017-11-09 20:38:30 -0800544 mCurrentBucketNum += numBucketsForward;
Yao Chen5154a3792017-10-30 22:57:06 -0700545}
546
Olivier Gaillard6c75ecd2019-02-20 09:57:33 +0000547void DurationMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
548 const int64_t& nextBucketStartTimeNs) {
Yangster-mac53928882018-02-25 23:02:56 -0800549 for (auto whatIt = mCurrentSlicedDurationTrackerMap.begin();
550 whatIt != mCurrentSlicedDurationTrackerMap.end();) {
tsaichristine81899f12020-01-08 12:42:12 -0800551 if (whatIt->second->flushCurrentBucket(eventTimeNs, &mPastBuckets)) {
552 VLOG("erase bucket for key %s", whatIt->first.toString().c_str());
Yangster-mac53928882018-02-25 23:02:56 -0800553 whatIt = mCurrentSlicedDurationTrackerMap.erase(whatIt);
David Chen27785a82018-01-19 17:06:45 -0800554 } else {
tsaichristine81899f12020-01-08 12:42:12 -0800555 ++whatIt;
David Chen27785a82018-01-19 17:06:45 -0800556 }
557 }
Olivier Gaillardf248c0d2019-02-21 15:56:58 +0000558 StatsdStats::getInstance().noteBucketCount(mMetricId);
Muhammad Qureshi902529a2019-03-14 16:03:21 -0700559 mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
David Chen27785a82018-01-19 17:06:45 -0800560}
561
Yao Chen884c8c12018-01-26 10:36:25 -0800562void DurationMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
Yangster-mac93694462018-01-22 20:49:31 -0800563 if (mCurrentSlicedDurationTrackerMap.size() == 0) {
Yao Chen884c8c12018-01-26 10:36:25 -0800564 return;
565 }
566
567 fprintf(out, "DurationMetric %lld dimension size %lu\n", (long long)mMetricId,
Yangster-mac93694462018-01-22 20:49:31 -0800568 (unsigned long)mCurrentSlicedDurationTrackerMap.size());
Yao Chen884c8c12018-01-26 10:36:25 -0800569 if (verbose) {
Yangster-mac53928882018-02-25 23:02:56 -0800570 for (const auto& whatIt : mCurrentSlicedDurationTrackerMap) {
tsaichristine81899f12020-01-08 12:42:12 -0800571 fprintf(out, "\t(what)%s\n", whatIt.first.toString().c_str());
572 whatIt.second->dumpStates(out, verbose);
Yao Chen884c8c12018-01-26 10:36:25 -0800573 }
574 }
575}
576
Yangster-mac93694462018-01-22 20:49:31 -0800577bool DurationMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) {
Yangster-mac306ccc22018-03-24 15:03:40 -0700578 auto whatIt = mCurrentSlicedDurationTrackerMap.find(newKey.getDimensionKeyInWhat());
tsaichristine81899f12020-01-08 12:42:12 -0800579 if (whatIt == mCurrentSlicedDurationTrackerMap.end()) {
Yangster-mac306ccc22018-03-24 15:03:40 -0700580 // 1. Report the tuple count if the tuple count > soft limit
581 if (mCurrentSlicedDurationTrackerMap.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
582 size_t newTupleCount = mCurrentSlicedDurationTrackerMap.size() + 1;
583 StatsdStats::getInstance().noteMetricDimensionSize(
584 mConfigKey, mMetricId, newTupleCount);
585 // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
586 if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
587 ALOGE("DurationMetric %lld dropping data for what dimension key %s",
588 (long long)mMetricId, newKey.getDimensionKeyInWhat().toString().c_str());
Muhammad Qureshi87348a62019-02-14 16:17:52 -0800589 StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
Yangster-mac306ccc22018-03-24 15:03:40 -0700590 return true;
591 }
Yao Chenb3561512017-11-21 18:07:17 -0800592 }
593 }
594 return false;
595}
596
Yangster-mac53928882018-02-25 23:02:56 -0800597void DurationMetricProducer::handleStartEvent(const MetricDimensionKey& eventKey,
598 const ConditionKey& conditionKeys,
599 bool condition, const LogEvent& event) {
600 const auto& whatKey = eventKey.getDimensionKeyInWhat();
Yangster-mac53928882018-02-25 23:02:56 -0800601 auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatKey);
602 if (whatIt == mCurrentSlicedDurationTrackerMap.end()) {
Yangsterf2bee6f2017-11-29 12:01:05 -0800603 if (hitGuardRailLocked(eventKey)) {
Yao Chenb3561512017-11-21 18:07:17 -0800604 return;
605 }
tsaichristine81899f12020-01-08 12:42:12 -0800606 mCurrentSlicedDurationTrackerMap[whatKey] = createDurationTracker(eventKey);
Yao Chen6a8c7992017-11-29 20:02:07 +0000607 }
Yao Chen5154a3792017-10-30 22:57:06 -0700608
tsaichristine81899f12020-01-08 12:42:12 -0800609 auto it = mCurrentSlicedDurationTrackerMap.find(whatKey);
Yangster-mac53928882018-02-25 23:02:56 -0800610 if (mUseWhatDimensionAsInternalDimension) {
tsaichristine1449fa42020-01-02 12:12:05 -0800611 it->second->noteStart(whatKey, condition, event.GetElapsedTimestampNs(), conditionKeys);
Yangster-mac53928882018-02-25 23:02:56 -0800612 return;
613 }
Yao Chen5154a3792017-10-30 22:57:06 -0700614
Yangster13fb7e42018-03-07 17:30:49 -0800615 if (mInternalDimensions.empty()) {
tsaichristine1449fa42020-01-02 12:12:05 -0800616 it->second->noteStart(DEFAULT_DIMENSION_KEY, condition, event.GetElapsedTimestampNs(),
617 conditionKeys);
Yangster-mac20877162017-12-22 17:19:39 -0800618 } else {
Yangster-mace06cfd72018-03-10 23:22:59 -0800619 HashableDimensionKey dimensionKey = DEFAULT_DIMENSION_KEY;
620 filterValues(mInternalDimensions, event.getValues(), &dimensionKey);
tsaichristine1449fa42020-01-02 12:12:05 -0800621 it->second->noteStart(dimensionKey, condition, event.GetElapsedTimestampNs(),
622 conditionKeys);
Yao Chen5154a3792017-10-30 22:57:06 -0700623 }
Yangster-mac20877162017-12-22 17:19:39 -0800624
Yao Chen729093d2017-10-16 10:33:26 -0700625}
626
Yangster-mac53928882018-02-25 23:02:56 -0800627void DurationMetricProducer::onMatchedLogEventInternalLocked(
628 const size_t matcherIndex, const MetricDimensionKey& eventKey,
tsaichristinec876b492019-12-10 13:47:05 -0800629 const ConditionKey& conditionKeys, bool condition, const LogEvent& event,
630 const map<int, HashableDimensionKey>& statePrimaryKeys) {
Yangster-mac53928882018-02-25 23:02:56 -0800631 ALOGW("Not used in duration tracker.");
632}
633
Yangster-mace06cfd72018-03-10 23:22:59 -0800634void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
635 const LogEvent& event) {
Yangster-macb142cc82018-03-30 15:22:08 -0700636 int64_t eventTimeNs = event.GetElapsedTimestampNs();
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700637 if (eventTimeNs < mTimeBaseNs) {
Yangster13fb7e42018-03-07 17:30:49 -0800638 return;
639 }
640
Muhammad Qureshi18e46922019-05-24 16:38:49 -0700641 if (mIsActive) {
642 flushIfNeededLocked(event.GetElapsedTimestampNs());
643 }
Yangster13fb7e42018-03-07 17:30:49 -0800644
645 // Handles Stopall events.
Tej Singhcfa32e12020-10-15 03:14:19 -0700646 if ((int)matcherIndex == mStopAllIndex) {
Yangster13fb7e42018-03-07 17:30:49 -0800647 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
tsaichristine81899f12020-01-08 12:42:12 -0800648 whatIt.second->noteStopAll(event.GetElapsedTimestampNs());
Yangster13fb7e42018-03-07 17:30:49 -0800649 }
650 return;
651 }
652
tsaichristine81899f12020-01-08 12:42:12 -0800653 HashableDimensionKey dimensionInWhat = DEFAULT_DIMENSION_KEY;
Yangster13fb7e42018-03-07 17:30:49 -0800654 if (!mDimensionsInWhat.empty()) {
655 filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat);
Yangster13fb7e42018-03-07 17:30:49 -0800656 }
657
tsaichristine1449fa42020-01-02 12:12:05 -0800658 // Stores atom id to primary key pairs for each state atom that the metric is
659 // sliced by.
660 std::map<int, HashableDimensionKey> statePrimaryKeys;
661
662 // For states with primary fields, use MetricStateLinks to get the primary
663 // field values from the log event. These values will form a primary key
664 // that will be used to query StateTracker for the correct state value.
665 for (const auto& stateLink : mMetric2StateLinks) {
666 getDimensionForState(event.getValues(), stateLink,
667 &statePrimaryKeys[stateLink.stateAtomId]);
668 }
669
670 // For each sliced state, query StateTracker for the state value using
671 // either the primary key from the previous step or the DEFAULT_DIMENSION_KEY.
672 //
673 // Expected functionality: for any case where the MetricStateLinks are
674 // initialized incorrectly (ex. # of state links != # of primary fields, no
675 // links are provided for a state with primary fields, links are provided
676 // in the wrong order, etc.), StateTracker will simply return kStateUnknown
677 // when queried using an incorrect key.
678 HashableDimensionKey stateValuesKey = DEFAULT_DIMENSION_KEY;
679 for (auto atomId : mSlicedStateAtoms) {
680 FieldValue value;
681 if (statePrimaryKeys.find(atomId) != statePrimaryKeys.end()) {
682 // found a primary key for this state, query using the key
683 queryStateValue(atomId, statePrimaryKeys[atomId], &value);
684 } else {
685 // if no MetricStateLinks exist for this state atom,
686 // query using the default dimension key (empty HashableDimensionKey)
687 queryStateValue(atomId, DEFAULT_DIMENSION_KEY, &value);
688 }
689 mapStateValue(atomId, &value);
690 stateValuesKey.addValue(value);
691 }
692
Yangster13fb7e42018-03-07 17:30:49 -0800693 // Handles Stop events.
Tej Singhcfa32e12020-10-15 03:14:19 -0700694 if ((int)matcherIndex == mStopIndex) {
Yangster13fb7e42018-03-07 17:30:49 -0800695 if (mUseWhatDimensionAsInternalDimension) {
696 auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat);
697 if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
tsaichristine81899f12020-01-08 12:42:12 -0800698 whatIt->second->noteStop(dimensionInWhat, event.GetElapsedTimestampNs(), false);
Yangster13fb7e42018-03-07 17:30:49 -0800699 }
700 return;
701 }
702
703 HashableDimensionKey internalDimensionKey = DEFAULT_DIMENSION_KEY;
704 if (!mInternalDimensions.empty()) {
705 filterValues(mInternalDimensions, event.getValues(), &internalDimensionKey);
706 }
707
708 auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat);
709 if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
tsaichristine81899f12020-01-08 12:42:12 -0800710 whatIt->second->noteStop(internalDimensionKey, event.GetElapsedTimestampNs(), false);
Yangster13fb7e42018-03-07 17:30:49 -0800711 }
712 return;
713 }
714
715 bool condition;
716 ConditionKey conditionKey;
Yangster13fb7e42018-03-07 17:30:49 -0800717 if (mConditionSliced) {
718 for (const auto& link : mMetric2ConditionLinks) {
719 getDimensionForCondition(event.getValues(), link, &conditionKey[link.conditionId]);
720 }
721
722 auto conditionState =
tsaichristine76853372019-08-06 17:17:03 -0700723 mWizard->query(mConditionTrackerIndex, conditionKey,
724 !mHasLinksToAllConditionDimensionsInTracker);
Olivier Gaillarde63d9e02019-02-12 14:43:59 +0000725 condition = conditionState == ConditionState::kTrue;
Yangster13fb7e42018-03-07 17:30:49 -0800726 } else {
Olivier Gaillarde63d9e02019-02-12 14:43:59 +0000727 // TODO: The unknown condition state is not handled here, we should fix it.
728 condition = mCondition == ConditionState::kTrue;
Yangster13fb7e42018-03-07 17:30:49 -0800729 }
730
Muhammad Qureshi18e46922019-05-24 16:38:49 -0700731 condition = condition && mIsActive;
732
tsaichristine1449fa42020-01-02 12:12:05 -0800733 handleStartEvent(MetricDimensionKey(dimensionInWhat, stateValuesKey), conditionKey, condition,
734 event);
Yangster13fb7e42018-03-07 17:30:49 -0800735}
736
Yangsterf2bee6f2017-11-29 12:01:05 -0800737size_t DurationMetricProducer::byteSizeLocked() const {
Yangster7c334a12017-11-22 14:24:24 -0800738 size_t totalSize = 0;
739 for (const auto& pair : mPastBuckets) {
740 totalSize += pair.second.size() * kBucketSize;
741 }
742 return totalSize;
yro69007c82017-10-26 20:42:57 -0700743}
744
Yao Chen729093d2017-10-16 10:33:26 -0700745} // namespace statsd
746} // namespace os
747} // namespace android