1 /*
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
17 #define STATSD_DEBUG false // STOPSHIP if true
18 #include "Log.h"
19
20 #include "metrics_manager_util.h"
21
22 #include <inttypes.h>
23
24 #include <variant>
25
26 #include "FieldValue.h"
27 #include "condition/CombinationConditionTracker.h"
28 #include "condition/SimpleConditionTracker.h"
29 #include "external/StatsPullerManager.h"
30 #include "guardrail/StatsdStats.h"
31 #include "hash.h"
32 #include "matchers/CombinationAtomMatchingTracker.h"
33 #include "matchers/EventMatcherWizard.h"
34 #include "matchers/SimpleAtomMatchingTracker.h"
35 #include "metrics/CountMetricProducer.h"
36 #include "metrics/DurationMetricProducer.h"
37 #include "metrics/EventMetricProducer.h"
38 #include "metrics/GaugeMetricProducer.h"
39 #include "metrics/KllMetricProducer.h"
40 #include "metrics/MetricProducer.h"
41 #include "metrics/NumericValueMetricProducer.h"
42 #include "metrics/RestrictedEventMetricProducer.h"
43 #include "metrics/parsing_utils/histogram_parsing_utils.h"
44 #include "state/StateManager.h"
45 #include "stats_util.h"
46
47 using google::protobuf::MessageLite;
48 using std::set;
49 using std::unordered_map;
50 using std::vector;
51
52 namespace android {
53 namespace os {
54 namespace statsd {
55
56 namespace {
57
hasLeafNode(const FieldMatcher & matcher)58 bool hasLeafNode(const FieldMatcher& matcher) {
59 if (!matcher.has_field()) {
60 return false;
61 }
62 for (int i = 0; i < matcher.child_size(); ++i) {
63 if (hasLeafNode(matcher.child(i))) {
64 return true;
65 }
66 }
67 return true;
68 }
69
70 // DFS for ensuring there is no
71 // 1. value matching in the FieldValueMatcher tree with Position::ALL.
72 // 2. string replacement in the FieldValueMatcher tree without a value matcher with Position::ANY.
73 // Using vector to keep track of visited FieldValueMatchers since we expect number of
74 // FieldValueMatchers to be low.
validateFvmPositionAllAndAny(const FieldValueMatcher & fvm,bool inPositionAll,bool inPositionAny,vector<FieldValueMatcher const * > & visited)75 optional<InvalidConfigReasonEnum> validateFvmPositionAllAndAny(
76 const FieldValueMatcher& fvm, bool inPositionAll, bool inPositionAny,
77 vector<FieldValueMatcher const*>& visited) {
78 visited.push_back(&fvm);
79 inPositionAll = inPositionAll || fvm.position() == Position::ALL;
80 inPositionAny = inPositionAny || fvm.position() == Position::ANY;
81 if (fvm.value_matcher_case() == FieldValueMatcher::kMatchesTuple) {
82 for (const FieldValueMatcher& childFvm : fvm.matches_tuple().field_value_matcher()) {
83 if (std::find(visited.cbegin(), visited.cend(), &childFvm) != visited.cend()) {
84 continue;
85 }
86 const optional<InvalidConfigReasonEnum> reasonEnum =
87 validateFvmPositionAllAndAny(childFvm, inPositionAll, inPositionAny, visited);
88 if (reasonEnum != nullopt) {
89 return reasonEnum;
90 }
91 }
92 return nullopt;
93 }
94 if (inPositionAll && fvm.value_matcher_case() != FieldValueMatcher::VALUE_MATCHER_NOT_SET) {
95 // value_matcher is set to something other than matches_tuple with Position::ALL
96 return INVALID_CONFIG_REASON_MATCHER_VALUE_MATCHER_WITH_POSITION_ALL;
97 }
98 if (inPositionAny && fvm.value_matcher_case() == FieldValueMatcher::VALUE_MATCHER_NOT_SET &&
99 fvm.has_replace_string()) {
100 // value_matcher is not set and there is a string replacement with Position::ANY
101 return INVALID_CONFIG_REASON_MATCHER_STRING_REPLACE_WITH_NO_VALUE_MATCHER_WITH_POSITION_ANY;
102 }
103 return nullopt;
104 }
105
validateSimpleAtomMatcher(int64_t matcherId,const SimpleAtomMatcher & simpleMatcher)106 optional<InvalidConfigReason> validateSimpleAtomMatcher(int64_t matcherId,
107 const SimpleAtomMatcher& simpleMatcher) {
108 for (const FieldValueMatcher& fvm : simpleMatcher.field_value_matcher()) {
109 if (fvm.value_matcher_case() == FieldValueMatcher::VALUE_MATCHER_NOT_SET &&
110 !fvm.has_replace_string()) {
111 return createInvalidConfigReasonWithMatcher(
112 INVALID_CONFIG_REASON_MATCHER_NO_VALUE_MATCHER_NOR_STRING_REPLACER, matcherId);
113 } else if (fvm.has_replace_string() &&
114 !(fvm.value_matcher_case() == FieldValueMatcher::VALUE_MATCHER_NOT_SET ||
115 fvm.value_matcher_case() == FieldValueMatcher::kEqString ||
116 fvm.value_matcher_case() == FieldValueMatcher::kEqAnyString ||
117 fvm.value_matcher_case() == FieldValueMatcher::kNeqAnyString ||
118 fvm.value_matcher_case() == FieldValueMatcher::kEqWildcardString ||
119 fvm.value_matcher_case() == FieldValueMatcher::kEqAnyWildcardString ||
120 fvm.value_matcher_case() == FieldValueMatcher::kNeqAnyWildcardString)) {
121 return createInvalidConfigReasonWithMatcher(
122 INVALID_CONFIG_REASON_MATCHER_INVALID_VALUE_MATCHER_WITH_STRING_REPLACE,
123 matcherId);
124 }
125 vector<FieldValueMatcher const*> visited;
126 const optional<InvalidConfigReasonEnum> reasonEnum = validateFvmPositionAllAndAny(
127 fvm, false /* inPositionAll */, false /* inPositionAny */, visited);
128 if (reasonEnum != nullopt) {
129 return createInvalidConfigReasonWithMatcher(*reasonEnum, matcherId);
130 }
131 }
132 return nullopt;
133 }
134
135 } // namespace
136
createAtomMatchingTracker(const AtomMatcher & logMatcher,const sp<UidMap> & uidMap,optional<InvalidConfigReason> & invalidConfigReason)137 sp<AtomMatchingTracker> createAtomMatchingTracker(
138 const AtomMatcher& logMatcher, const sp<UidMap>& uidMap,
139 optional<InvalidConfigReason>& invalidConfigReason) {
140 string serializedMatcher;
141 if (!logMatcher.SerializeToString(&serializedMatcher)) {
142 ALOGE("Unable to serialize matcher %lld", (long long)logMatcher.id());
143 invalidConfigReason = createInvalidConfigReasonWithMatcher(
144 INVALID_CONFIG_REASON_MATCHER_SERIALIZATION_FAILED, logMatcher.id());
145 return nullptr;
146 }
147 uint64_t protoHash = Hash64(serializedMatcher);
148 switch (logMatcher.contents_case()) {
149 case AtomMatcher::ContentsCase::kSimpleAtomMatcher: {
150 invalidConfigReason =
151 validateSimpleAtomMatcher(logMatcher.id(), logMatcher.simple_atom_matcher());
152 if (invalidConfigReason != nullopt) {
153 ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
154 return nullptr;
155 }
156 sp<AtomMatchingTracker> simpleAtomMatcher = new SimpleAtomMatchingTracker(
157 logMatcher.id(), protoHash, logMatcher.simple_atom_matcher(), uidMap);
158 return simpleAtomMatcher;
159 }
160 case AtomMatcher::ContentsCase::kCombination:
161 return new CombinationAtomMatchingTracker(logMatcher.id(), protoHash);
162 default:
163 ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
164 invalidConfigReason = createInvalidConfigReasonWithMatcher(
165 INVALID_CONFIG_REASON_MATCHER_MALFORMED_CONTENTS_CASE, logMatcher.id());
166 return nullptr;
167 }
168 }
169
createConditionTracker(const ConfigKey & key,const Predicate & predicate,const int index,const unordered_map<int64_t,int> & atomMatchingTrackerMap,optional<InvalidConfigReason> & invalidConfigReason)170 sp<ConditionTracker> createConditionTracker(
171 const ConfigKey& key, const Predicate& predicate, const int index,
172 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
173 optional<InvalidConfigReason>& invalidConfigReason) {
174 string serializedPredicate;
175 if (!predicate.SerializeToString(&serializedPredicate)) {
176 ALOGE("Unable to serialize predicate %lld", (long long)predicate.id());
177 invalidConfigReason = createInvalidConfigReasonWithPredicate(
178 INVALID_CONFIG_REASON_CONDITION_SERIALIZATION_FAILED, predicate.id());
179 return nullptr;
180 }
181 uint64_t protoHash = Hash64(serializedPredicate);
182 switch (predicate.contents_case()) {
183 case Predicate::ContentsCase::kSimplePredicate: {
184 return new SimpleConditionTracker(key, predicate.id(), protoHash, index,
185 predicate.simple_predicate(), atomMatchingTrackerMap);
186 }
187 case Predicate::ContentsCase::kCombination: {
188 return new CombinationConditionTracker(predicate.id(), index, protoHash);
189 }
190 default:
191 ALOGE("Predicate \"%lld\" malformed", (long long)predicate.id());
192 invalidConfigReason = createInvalidConfigReasonWithPredicate(
193 INVALID_CONFIG_REASON_CONDITION_MALFORMED_CONTENTS_CASE, predicate.id());
194 return nullptr;
195 }
196 }
197
getMetricProtoHash(const StatsdConfig & config,const MessageLite & metric,const int64_t id,const unordered_map<int64_t,int> & metricToActivationMap,uint64_t & metricHash)198 optional<InvalidConfigReason> getMetricProtoHash(
199 const StatsdConfig& config, const MessageLite& metric, const int64_t id,
200 const unordered_map<int64_t, int>& metricToActivationMap, uint64_t& metricHash) {
201 string serializedMetric;
202 if (!metric.SerializeToString(&serializedMetric)) {
203 ALOGE("Unable to serialize metric %lld", (long long)id);
204 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SERIALIZATION_FAILED, id);
205 }
206 metricHash = Hash64(serializedMetric);
207
208 // Combine with activation hash, if applicable
209 const auto& metricActivationIt = metricToActivationMap.find(id);
210 if (metricActivationIt != metricToActivationMap.end()) {
211 string serializedActivation;
212 const MetricActivation& activation = config.metric_activation(metricActivationIt->second);
213 if (!activation.SerializeToString(&serializedActivation)) {
214 ALOGE("Unable to serialize metric activation for metric %lld", (long long)id);
215 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_ACTIVATION_SERIALIZATION_FAILED,
216 id);
217 }
218 metricHash = Hash64(to_string(metricHash).append(to_string(Hash64(serializedActivation))));
219 }
220 return nullopt;
221 }
222
handleMetricWithAtomMatchingTrackers(const int64_t matcherId,const int64_t metricId,const int metricIndex,const bool enforceOneAtom,const vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,const unordered_map<int64_t,int> & atomMatchingTrackerMap,unordered_map<int,vector<int>> & trackerToMetricMap,int & logTrackerIndex)223 optional<InvalidConfigReason> handleMetricWithAtomMatchingTrackers(
224 const int64_t matcherId, const int64_t metricId, const int metricIndex,
225 const bool enforceOneAtom, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
226 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
227 unordered_map<int, vector<int>>& trackerToMetricMap, int& logTrackerIndex) {
228 auto logTrackerIt = atomMatchingTrackerMap.find(matcherId);
229 if (logTrackerIt == atomMatchingTrackerMap.end()) {
230 ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)matcherId);
231 return createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_METRIC_MATCHER_NOT_FOUND,
232 metricId, matcherId);
233 }
234 if (enforceOneAtom && allAtomMatchingTrackers[logTrackerIt->second]->getAtomIds().size() > 1) {
235 ALOGE("AtomMatcher \"%lld\" has more than one tag ids. When a metric has dimension, "
236 "the \"what\" can only be about one atom type. trigger_event matchers can also only "
237 "be about one atom type.",
238 (long long)matcherId);
239 return createInvalidConfigReasonWithMatcher(
240 INVALID_CONFIG_REASON_METRIC_MATCHER_MORE_THAN_ONE_ATOM, metricId, matcherId);
241 }
242 logTrackerIndex = logTrackerIt->second;
243 auto& metric_list = trackerToMetricMap[logTrackerIndex];
244 metric_list.push_back(metricIndex);
245 return nullopt;
246 }
247
handleMetricWithConditions(const int64_t condition,const int64_t metricId,const int metricIndex,const unordered_map<int64_t,int> & conditionTrackerMap,const::google::protobuf::RepeatedPtrField<MetricConditionLink> & links,const vector<sp<ConditionTracker>> & allConditionTrackers,int & conditionIndex,unordered_map<int,vector<int>> & conditionToMetricMap)248 optional<InvalidConfigReason> handleMetricWithConditions(
249 const int64_t condition, const int64_t metricId, const int metricIndex,
250 const unordered_map<int64_t, int>& conditionTrackerMap,
251 const ::google::protobuf::RepeatedPtrField<MetricConditionLink>& links,
252 const vector<sp<ConditionTracker>>& allConditionTrackers, int& conditionIndex,
253 unordered_map<int, vector<int>>& conditionToMetricMap) {
254 auto condition_it = conditionTrackerMap.find(condition);
255 if (condition_it == conditionTrackerMap.end()) {
256 ALOGW("cannot find Predicate \"%lld\" in the config", (long long)condition);
257 return createInvalidConfigReasonWithPredicate(
258 INVALID_CONFIG_REASON_METRIC_CONDITION_NOT_FOUND, metricId, condition);
259 }
260 for (const auto& link : links) {
261 auto it = conditionTrackerMap.find(link.condition());
262 if (it == conditionTrackerMap.end()) {
263 ALOGW("cannot find Predicate \"%lld\" in the config", (long long)link.condition());
264 return createInvalidConfigReasonWithPredicate(
265 INVALID_CONFIG_REASON_METRIC_CONDITION_LINK_NOT_FOUND, metricId,
266 link.condition());
267 }
268 }
269 conditionIndex = condition_it->second;
270
271 // will create new vector if not exist before.
272 auto& metricList = conditionToMetricMap[condition_it->second];
273 metricList.push_back(metricIndex);
274 return nullopt;
275 }
276
277 // Initializes state data structures for a metric.
278 // input:
279 // [config]: the input config
280 // [stateIds]: the slice_by_state ids for this metric
281 // [stateAtomIdMap]: this map contains the mapping from all state ids to atom ids
282 // [allStateGroupMaps]: this map contains the mapping from state ids and state
283 // values to state group ids for all states
284 // output:
285 // [slicedStateAtoms]: a vector of atom ids of all the slice_by_states
286 // [stateGroupMap]: this map should contain the mapping from states ids and state
287 // values to state group ids for all states that this metric
288 // is interested in
handleMetricWithStates(const StatsdConfig & config,const int64_t metricId,const::google::protobuf::RepeatedField<int64_t> & stateIds,const unordered_map<int64_t,int> & stateAtomIdMap,const unordered_map<int64_t,unordered_map<int,int64_t>> & allStateGroupMaps,vector<int> & slicedStateAtoms,unordered_map<int,unordered_map<int,int64_t>> & stateGroupMap)289 optional<InvalidConfigReason> handleMetricWithStates(
290 const StatsdConfig& config, const int64_t metricId,
291 const ::google::protobuf::RepeatedField<int64_t>& stateIds,
292 const unordered_map<int64_t, int>& stateAtomIdMap,
293 const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
294 vector<int>& slicedStateAtoms,
295 unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap) {
296 for (const auto& stateId : stateIds) {
297 auto it = stateAtomIdMap.find(stateId);
298 if (it == stateAtomIdMap.end()) {
299 ALOGW("cannot find State %" PRId64 " in the config", stateId);
300 return createInvalidConfigReasonWithState(INVALID_CONFIG_REASON_METRIC_STATE_NOT_FOUND,
301 metricId, stateId);
302 }
303 int atomId = it->second;
304 slicedStateAtoms.push_back(atomId);
305
306 auto stateIt = allStateGroupMaps.find(stateId);
307 if (stateIt != allStateGroupMaps.end()) {
308 stateGroupMap[atomId] = stateIt->second;
309 }
310 }
311 return nullopt;
312 }
313
handleMetricWithStateLink(const int64_t metricId,const FieldMatcher & stateMatcher,const vector<Matcher> & dimensionsInWhat)314 optional<InvalidConfigReason> handleMetricWithStateLink(const int64_t metricId,
315 const FieldMatcher& stateMatcher,
316 const vector<Matcher>& dimensionsInWhat) {
317 vector<Matcher> stateMatchers;
318 translateFieldMatcher(stateMatcher, &stateMatchers);
319 if (!subsetDimensions(stateMatchers, dimensionsInWhat)) {
320 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINKS_NOT_SUBSET_DIM_IN_WHAT,
321 metricId);
322 }
323 return nullopt;
324 }
325
handleMetricWithDimensionalSampling(const int64_t metricId,const DimensionalSamplingInfo & dimSamplingInfo,const vector<Matcher> & dimensionsInWhat,SamplingInfo & samplingInfo)326 optional<InvalidConfigReason> handleMetricWithDimensionalSampling(
327 const int64_t metricId, const DimensionalSamplingInfo& dimSamplingInfo,
328 const vector<Matcher>& dimensionsInWhat, SamplingInfo& samplingInfo) {
329 if (!dimSamplingInfo.has_sampled_what_field()) {
330 ALOGE("metric DimensionalSamplingInfo missing sampledWhatField");
331 return InvalidConfigReason(
332 INVALID_CONFIG_REASON_METRIC_DIMENSIONAL_SAMPLING_INFO_MISSING_SAMPLED_FIELD,
333 metricId);
334 }
335
336 if (dimSamplingInfo.shard_count() <= 1) {
337 ALOGE("metric shardCount must be > 1");
338 return InvalidConfigReason(
339 INVALID_CONFIG_REASON_METRIC_DIMENSIONAL_SAMPLING_INFO_INCORRECT_SHARD_COUNT,
340 metricId);
341 }
342 samplingInfo.shardCount = dimSamplingInfo.shard_count();
343
344 if (HasPositionALL(dimSamplingInfo.sampled_what_field()) ||
345 HasPositionANY(dimSamplingInfo.sampled_what_field())) {
346 ALOGE("metric has repeated field with position ALL or ANY as the sampled dimension");
347 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELD_INCORRECT_SIZE,
348 metricId);
349 }
350
351 translateFieldMatcher(dimSamplingInfo.sampled_what_field(), &samplingInfo.sampledWhatFields);
352 if (samplingInfo.sampledWhatFields.size() != 1) {
353 ALOGE("metric has incorrect number of sampled dimension fields");
354 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELD_INCORRECT_SIZE,
355 metricId);
356 }
357 if (!subsetDimensions(samplingInfo.sampledWhatFields, dimensionsInWhat)) {
358 return InvalidConfigReason(
359 INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELDS_NOT_SUBSET_DIM_IN_WHAT, metricId);
360 }
361 return nullopt;
362 }
363
364 template <typename T>
setUidFieldsIfNecessary(const T & metric,sp<MetricProducer> metricProducer)365 optional<InvalidConfigReason> setUidFieldsIfNecessary(const T& metric,
366 sp<MetricProducer> metricProducer) {
367 if (metric.has_uid_fields()) {
368 if (HasPositionANY(metric.uid_fields())) {
369 ALOGE("Metric %lld has position ANY in uid fields", (long long)metric.id());
370 return InvalidConfigReason(INVALID_CONFIG_REASON_UID_FIELDS_WITH_POSITION_ANY,
371 metric.id());
372 }
373 std::vector<Matcher> uidFields;
374 translateFieldMatcher(metric.uid_fields(), &uidFields);
375 metricProducer->setUidFields(uidFields);
376 }
377 return nullopt;
378 }
379
380 // Validates a metricActivation and populates state.
381 // EventActivationMap and EventDeactivationMap are supplied to a MetricProducer
382 // to provide the producer with state about its activators and deactivators.
383 // Returns false if there are errors.
handleMetricActivation(const StatsdConfig & config,const int64_t metricId,const int metricIndex,const unordered_map<int64_t,int> & metricToActivationMap,const unordered_map<int64_t,int> & atomMatchingTrackerMap,unordered_map<int,vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation,unordered_map<int,shared_ptr<Activation>> & eventActivationMap,unordered_map<int,vector<shared_ptr<Activation>>> & eventDeactivationMap)384 optional<InvalidConfigReason> handleMetricActivation(
385 const StatsdConfig& config, const int64_t metricId, const int metricIndex,
386 const unordered_map<int64_t, int>& metricToActivationMap,
387 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
388 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
389 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
390 vector<int>& metricsWithActivation,
391 unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
392 unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap) {
393 // Check if metric has an associated activation
394 auto itr = metricToActivationMap.find(metricId);
395 if (itr == metricToActivationMap.end()) {
396 return nullopt;
397 }
398
399 int activationIndex = itr->second;
400 const MetricActivation& metricActivation = config.metric_activation(activationIndex);
401
402 for (int i = 0; i < metricActivation.event_activation_size(); i++) {
403 const EventActivation& activation = metricActivation.event_activation(i);
404
405 auto itr = atomMatchingTrackerMap.find(activation.atom_matcher_id());
406 if (itr == atomMatchingTrackerMap.end()) {
407 ALOGE("Atom matcher not found for event activation.");
408 return createInvalidConfigReasonWithMatcher(
409 INVALID_CONFIG_REASON_METRIC_ACTIVATION_MATCHER_NOT_FOUND, metricId,
410 activation.atom_matcher_id());
411 }
412
413 ActivationType activationType = (activation.has_activation_type())
414 ? activation.activation_type()
415 : metricActivation.activation_type();
416 std::shared_ptr<Activation> activationWrapper =
417 std::make_shared<Activation>(activationType, activation.ttl_seconds() * NS_PER_SEC);
418
419 int atomMatcherIndex = itr->second;
420 activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(metricIndex);
421 eventActivationMap.emplace(atomMatcherIndex, activationWrapper);
422
423 if (activation.has_deactivation_atom_matcher_id()) {
424 itr = atomMatchingTrackerMap.find(activation.deactivation_atom_matcher_id());
425 if (itr == atomMatchingTrackerMap.end()) {
426 ALOGE("Atom matcher not found for event deactivation.");
427 return createInvalidConfigReasonWithMatcher(
428 INVALID_CONFIG_REASON_METRIC_DEACTIVATION_MATCHER_NOT_FOUND, metricId,
429 activation.deactivation_atom_matcher_id());
430 }
431 int deactivationAtomMatcherIndex = itr->second;
432 deactivationAtomTrackerToMetricMap[deactivationAtomMatcherIndex].push_back(metricIndex);
433 eventDeactivationMap[deactivationAtomMatcherIndex].push_back(activationWrapper);
434 }
435 }
436
437 metricsWithActivation.push_back(metricIndex);
438 return nullopt;
439 }
440
441 // Validates a metricActivation and populates state.
442 // Fills the new event activation/deactivation maps, preserving the existing activations
443 // Returns false if there are errors.
handleMetricActivationOnConfigUpdate(const StatsdConfig & config,const int64_t metricId,const int metricIndex,const unordered_map<int64_t,int> & metricToActivationMap,const unordered_map<int64_t,int> & oldAtomMatchingTrackerMap,const unordered_map<int64_t,int> & newAtomMatchingTrackerMap,const unordered_map<int,shared_ptr<Activation>> & oldEventActivationMap,unordered_map<int,vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation,unordered_map<int,shared_ptr<Activation>> & newEventActivationMap,unordered_map<int,vector<shared_ptr<Activation>>> & newEventDeactivationMap)444 optional<InvalidConfigReason> handleMetricActivationOnConfigUpdate(
445 const StatsdConfig& config, const int64_t metricId, const int metricIndex,
446 const unordered_map<int64_t, int>& metricToActivationMap,
447 const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
448 const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
449 const unordered_map<int, shared_ptr<Activation>>& oldEventActivationMap,
450 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
451 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
452 vector<int>& metricsWithActivation,
453 unordered_map<int, shared_ptr<Activation>>& newEventActivationMap,
454 unordered_map<int, vector<shared_ptr<Activation>>>& newEventDeactivationMap) {
455 // Check if metric has an associated activation.
456 const auto& itr = metricToActivationMap.find(metricId);
457 if (itr == metricToActivationMap.end()) {
458 return nullopt;
459 }
460
461 int activationIndex = itr->second;
462 const MetricActivation& metricActivation = config.metric_activation(activationIndex);
463
464 for (int i = 0; i < metricActivation.event_activation_size(); i++) {
465 const int64_t activationMatcherId = metricActivation.event_activation(i).atom_matcher_id();
466
467 const auto& newActivationIt = newAtomMatchingTrackerMap.find(activationMatcherId);
468 if (newActivationIt == newAtomMatchingTrackerMap.end()) {
469 ALOGE("Atom matcher not found in new config for event activation.");
470 return createInvalidConfigReasonWithMatcher(
471 INVALID_CONFIG_REASON_METRIC_ACTIVATION_MATCHER_NOT_FOUND_NEW, metricId,
472 activationMatcherId);
473 }
474 int newActivationMatcherIndex = newActivationIt->second;
475
476 // Find the old activation struct and copy it over.
477 const auto& oldActivationIt = oldAtomMatchingTrackerMap.find(activationMatcherId);
478 if (oldActivationIt == oldAtomMatchingTrackerMap.end()) {
479 ALOGE("Atom matcher not found in existing config for event activation.");
480 return createInvalidConfigReasonWithMatcher(
481 INVALID_CONFIG_REASON_METRIC_ACTIVATION_MATCHER_NOT_FOUND_EXISTING, metricId,
482 activationMatcherId);
483 }
484 int oldActivationMatcherIndex = oldActivationIt->second;
485 const auto& oldEventActivationIt = oldEventActivationMap.find(oldActivationMatcherIndex);
486 if (oldEventActivationIt == oldEventActivationMap.end()) {
487 ALOGE("Could not find existing event activation to update");
488 return createInvalidConfigReasonWithMatcher(
489 INVALID_CONFIG_REASON_METRIC_ACTIVATION_NOT_FOUND_EXISTING, metricId,
490 activationMatcherId);
491 }
492 newEventActivationMap.emplace(newActivationMatcherIndex, oldEventActivationIt->second);
493 activationAtomTrackerToMetricMap[newActivationMatcherIndex].push_back(metricIndex);
494
495 if (metricActivation.event_activation(i).has_deactivation_atom_matcher_id()) {
496 const int64_t deactivationMatcherId =
497 metricActivation.event_activation(i).deactivation_atom_matcher_id();
498 const auto& newDeactivationIt = newAtomMatchingTrackerMap.find(deactivationMatcherId);
499 if (newDeactivationIt == newAtomMatchingTrackerMap.end()) {
500 ALOGE("Deactivation atom matcher not found in new config for event activation.");
501 return createInvalidConfigReasonWithMatcher(
502 INVALID_CONFIG_REASON_METRIC_DEACTIVATION_MATCHER_NOT_FOUND_NEW, metricId,
503 deactivationMatcherId);
504 }
505 int newDeactivationMatcherIndex = newDeactivationIt->second;
506 newEventDeactivationMap[newDeactivationMatcherIndex].push_back(
507 oldEventActivationIt->second);
508 deactivationAtomTrackerToMetricMap[newDeactivationMatcherIndex].push_back(metricIndex);
509 }
510 }
511
512 metricsWithActivation.push_back(metricIndex);
513 return nullopt;
514 }
515
createCountMetricProducerAndUpdateMetadata(const ConfigKey & key,const StatsdConfig & config,const int64_t timeBaseNs,const int64_t currentTimeNs,const CountMetric & metric,const int metricIndex,const vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,const unordered_map<int64_t,int> & atomMatchingTrackerMap,vector<sp<ConditionTracker>> & allConditionTrackers,const unordered_map<int64_t,int> & conditionTrackerMap,const vector<ConditionState> & initialConditionCache,const sp<ConditionWizard> & wizard,const unordered_map<int64_t,int> & stateAtomIdMap,const unordered_map<int64_t,unordered_map<int,int64_t>> & allStateGroupMaps,const unordered_map<int64_t,int> & metricToActivationMap,unordered_map<int,vector<int>> & trackerToMetricMap,unordered_map<int,vector<int>> & conditionToMetricMap,unordered_map<int,vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation,optional<InvalidConfigReason> & invalidConfigReason,const wp<ConfigMetadataProvider> configMetadataProvider)516 optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata(
517 const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
518 const int64_t currentTimeNs, const CountMetric& metric, const int metricIndex,
519 const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
520 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
521 vector<sp<ConditionTracker>>& allConditionTrackers,
522 const unordered_map<int64_t, int>& conditionTrackerMap,
523 const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
524 const unordered_map<int64_t, int>& stateAtomIdMap,
525 const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
526 const unordered_map<int64_t, int>& metricToActivationMap,
527 unordered_map<int, vector<int>>& trackerToMetricMap,
528 unordered_map<int, vector<int>>& conditionToMetricMap,
529 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
530 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
531 vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason,
532 const wp<ConfigMetadataProvider> configMetadataProvider) {
533 if (!metric.has_id() || !metric.has_what()) {
534 ALOGE("cannot find metric id or \"what\" in CountMetric \"%lld\"", (long long)metric.id());
535 invalidConfigReason =
536 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
537 return nullopt;
538 }
539 int trackerIndex;
540 invalidConfigReason = handleMetricWithAtomMatchingTrackers(
541 metric.what(), metric.id(), metricIndex, metric.has_dimensions_in_what(),
542 allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, trackerIndex);
543 if (invalidConfigReason.has_value()) {
544 return nullopt;
545 }
546
547 int conditionIndex = -1;
548 if (metric.has_condition()) {
549 invalidConfigReason = handleMetricWithConditions(
550 metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
551 allConditionTrackers, conditionIndex, conditionToMetricMap);
552 if (invalidConfigReason.has_value()) {
553 return nullopt;
554 }
555 } else {
556 if (metric.links_size() > 0) {
557 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
558 invalidConfigReason = InvalidConfigReason(
559 INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
560 return nullopt;
561 }
562 }
563
564 std::vector<int> slicedStateAtoms;
565 unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
566 if (metric.slice_by_state_size() > 0) {
567 invalidConfigReason =
568 handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
569 allStateGroupMaps, slicedStateAtoms, stateGroupMap);
570 if (invalidConfigReason.has_value()) {
571 return nullopt;
572 }
573 } else {
574 if (metric.state_link_size() > 0) {
575 ALOGW("CountMetric has a MetricStateLink but doesn't have a slice_by_state");
576 invalidConfigReason = InvalidConfigReason(
577 INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
578 return nullopt;
579 }
580 }
581
582 // Check that all metric state links are a subset of dimensions_in_what fields.
583 std::vector<Matcher> dimensionsInWhat;
584 translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
585 for (const auto& stateLink : metric.state_link()) {
586 invalidConfigReason = handleMetricWithStateLink(metric.id(), stateLink.fields_in_what(),
587 dimensionsInWhat);
588 if (invalidConfigReason.has_value()) {
589 ALOGW("CountMetric's MetricStateLinks must be a subset of dimensions in what");
590 return nullopt;
591 }
592 }
593
594 unordered_map<int, shared_ptr<Activation>> eventActivationMap;
595 unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
596 invalidConfigReason = handleMetricActivation(
597 config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
598 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
599 metricsWithActivation, eventActivationMap, eventDeactivationMap);
600 if (invalidConfigReason.has_value()) {
601 return nullopt;
602 }
603
604 uint64_t metricHash;
605 invalidConfigReason =
606 getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
607 if (invalidConfigReason.has_value()) {
608 return nullopt;
609 }
610
611 if (metric.has_threshold() &&
612 (metric.threshold().value_comparison_case() == UploadThreshold::kLtFloat ||
613 metric.threshold().value_comparison_case() == UploadThreshold::kGtFloat)) {
614 ALOGW("Count metric incorrect upload threshold type or no type used");
615 invalidConfigReason =
616 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_BAD_THRESHOLD, metric.id());
617 return nullopt;
618 }
619
620 sp<MetricProducer> metricProducer = new CountMetricProducer(
621 key, metric, conditionIndex, initialConditionCache, wizard, metricHash, timeBaseNs,
622 currentTimeNs, configMetadataProvider, eventActivationMap, eventDeactivationMap,
623 slicedStateAtoms, stateGroupMap);
624
625 SamplingInfo samplingInfo;
626 if (metric.has_dimensional_sampling_info()) {
627 invalidConfigReason = handleMetricWithDimensionalSampling(
628 metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
629 if (invalidConfigReason.has_value()) {
630 return nullopt;
631 }
632 metricProducer->setSamplingInfo(samplingInfo);
633 }
634
635 invalidConfigReason = setUidFieldsIfNecessary(metric, metricProducer);
636 if (invalidConfigReason.has_value()) {
637 return nullopt;
638 }
639 return metricProducer;
640 }
641
createDurationMetricProducerAndUpdateMetadata(const ConfigKey & key,const StatsdConfig & config,const int64_t timeBaseNs,const int64_t currentTimeNs,const DurationMetric & metric,const int metricIndex,const vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,const unordered_map<int64_t,int> & atomMatchingTrackerMap,vector<sp<ConditionTracker>> & allConditionTrackers,const unordered_map<int64_t,int> & conditionTrackerMap,const vector<ConditionState> & initialConditionCache,const sp<ConditionWizard> & wizard,const unordered_map<int64_t,int> & stateAtomIdMap,const unordered_map<int64_t,unordered_map<int,int64_t>> & allStateGroupMaps,const unordered_map<int64_t,int> & metricToActivationMap,unordered_map<int,vector<int>> & trackerToMetricMap,unordered_map<int,vector<int>> & conditionToMetricMap,unordered_map<int,vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation,optional<InvalidConfigReason> & invalidConfigReason,const wp<ConfigMetadataProvider> configMetadataProvider)642 optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
643 const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
644 const int64_t currentTimeNs, const DurationMetric& metric, const int metricIndex,
645 const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
646 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
647 vector<sp<ConditionTracker>>& allConditionTrackers,
648 const unordered_map<int64_t, int>& conditionTrackerMap,
649 const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
650 const unordered_map<int64_t, int>& stateAtomIdMap,
651 const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
652 const unordered_map<int64_t, int>& metricToActivationMap,
653 unordered_map<int, vector<int>>& trackerToMetricMap,
654 unordered_map<int, vector<int>>& conditionToMetricMap,
655 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
656 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
657 vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason,
658 const wp<ConfigMetadataProvider> configMetadataProvider) {
659 if (!metric.has_id() || !metric.has_what()) {
660 ALOGE("cannot find metric id or \"what\" in DurationMetric \"%lld\"",
661 (long long)metric.id());
662 invalidConfigReason =
663 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
664 return nullopt;
665 }
666 const auto& what_it = conditionTrackerMap.find(metric.what());
667 if (what_it == conditionTrackerMap.end()) {
668 ALOGE("DurationMetric's \"what\" is not present in the condition trackers");
669 invalidConfigReason = createInvalidConfigReasonWithPredicate(
670 INVALID_CONFIG_REASON_DURATION_METRIC_WHAT_NOT_FOUND, metric.id(), metric.what());
671 return nullopt;
672 }
673
674 const int whatIndex = what_it->second;
675 const Predicate& durationWhat = config.predicate(whatIndex);
676 if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
677 ALOGE("DurationMetric's \"what\" must be a simple condition");
678 invalidConfigReason = createInvalidConfigReasonWithPredicate(
679 INVALID_CONFIG_REASON_DURATION_METRIC_WHAT_NOT_SIMPLE, metric.id(), metric.what());
680 return nullopt;
681 }
682
683 const SimplePredicate& simplePredicate = durationWhat.simple_predicate();
684 bool nesting = simplePredicate.count_nesting();
685
686 int startIndex = -1, stopIndex = -1, stopAllIndex = -1;
687 if (!simplePredicate.has_start()) {
688 ALOGE("Duration metrics must specify a valid start event matcher");
689 invalidConfigReason = createInvalidConfigReasonWithPredicate(
690 INVALID_CONFIG_REASON_DURATION_METRIC_MISSING_START, metric.id(), metric.what());
691 return nullopt;
692 }
693 invalidConfigReason = handleMetricWithAtomMatchingTrackers(
694 simplePredicate.start(), metric.id(), metricIndex, metric.has_dimensions_in_what(),
695 allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, startIndex);
696 if (invalidConfigReason.has_value()) {
697 return nullopt;
698 }
699
700 if (simplePredicate.has_stop()) {
701 invalidConfigReason = handleMetricWithAtomMatchingTrackers(
702 simplePredicate.stop(), metric.id(), metricIndex, metric.has_dimensions_in_what(),
703 allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, stopIndex);
704 if (invalidConfigReason.has_value()) {
705 return nullopt;
706 }
707 }
708
709 if (simplePredicate.has_stop_all()) {
710 invalidConfigReason = handleMetricWithAtomMatchingTrackers(
711 simplePredicate.stop_all(), metric.id(), metricIndex,
712 metric.has_dimensions_in_what(), allAtomMatchingTrackers, atomMatchingTrackerMap,
713 trackerToMetricMap, stopAllIndex);
714 if (invalidConfigReason.has_value()) {
715 return nullopt;
716 }
717 }
718
719 const FieldMatcher& internalDimensions = simplePredicate.dimensions();
720
721 int conditionIndex = -1;
722 if (metric.has_condition()) {
723 invalidConfigReason = handleMetricWithConditions(
724 metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
725 allConditionTrackers, conditionIndex, conditionToMetricMap);
726 if (invalidConfigReason.has_value()) {
727 return nullopt;
728 }
729 } else if (metric.links_size() > 0) {
730 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
731 invalidConfigReason = InvalidConfigReason(
732 INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
733 return nullopt;
734 }
735
736 std::vector<int> slicedStateAtoms;
737 unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
738 if (metric.slice_by_state_size() > 0) {
739 if (metric.aggregation_type() == DurationMetric::MAX_SPARSE) {
740 ALOGE("DurationMetric with aggregation type MAX_SPARSE cannot be sliced by state");
741 invalidConfigReason = InvalidConfigReason(
742 INVALID_CONFIG_REASON_DURATION_METRIC_MAX_SPARSE_HAS_SLICE_BY_STATE,
743 metric.id());
744 return nullopt;
745 }
746 invalidConfigReason =
747 handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
748 allStateGroupMaps, slicedStateAtoms, stateGroupMap);
749 if (invalidConfigReason.has_value()) {
750 return nullopt;
751 }
752 } else if (metric.state_link_size() > 0) {
753 ALOGW("DurationMetric has a MetricStateLink but doesn't have a sliced state");
754 invalidConfigReason =
755 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
756 return nullopt;
757 }
758
759 // Check that all metric state links are a subset of dimensions_in_what fields.
760 std::vector<Matcher> dimensionsInWhat;
761 translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
762 for (const auto& stateLink : metric.state_link()) {
763 invalidConfigReason = handleMetricWithStateLink(metric.id(), stateLink.fields_in_what(),
764 dimensionsInWhat);
765 if (invalidConfigReason.has_value()) {
766 ALOGW("DurationMetric's MetricStateLinks must be a subset of dimensions in what");
767 return nullopt;
768 }
769 }
770
771 unordered_map<int, shared_ptr<Activation>> eventActivationMap;
772 unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
773 invalidConfigReason = handleMetricActivation(
774 config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
775 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
776 metricsWithActivation, eventActivationMap, eventDeactivationMap);
777 if (invalidConfigReason.has_value()) {
778 return nullopt;
779 }
780
781 uint64_t metricHash;
782 invalidConfigReason =
783 getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
784 if (invalidConfigReason.has_value()) {
785 return nullopt;
786 }
787
788 if (metric.has_threshold()) {
789 switch (metric.threshold().value_comparison_case()) {
790 case UploadThreshold::kLtInt:
791 case UploadThreshold::kGtInt:
792 case UploadThreshold::kLteInt:
793 case UploadThreshold::kGteInt:
794 break;
795 default:
796 ALOGE("Duration metric incorrect upload threshold type or no type used");
797 invalidConfigReason = InvalidConfigReason(
798 INVALID_CONFIG_REASON_METRIC_BAD_THRESHOLD, metric.id());
799 return nullopt;
800 }
801 }
802
803 sp<MetricProducer> metricProducer = new DurationMetricProducer(
804 key, metric, conditionIndex, initialConditionCache, whatIndex, startIndex, stopIndex,
805 stopAllIndex, nesting, wizard, metricHash, internalDimensions, timeBaseNs,
806 currentTimeNs, configMetadataProvider, eventActivationMap, eventDeactivationMap,
807 slicedStateAtoms, stateGroupMap);
808 if (!metricProducer->isValid()) {
809 // TODO: Remove once invalidConfigReason is added to the DurationMetricProducer constructor
810 invalidConfigReason = InvalidConfigReason(
811 INVALID_CONFIG_REASON_DURATION_METRIC_PRODUCER_INVALID, metric.id());
812 return nullopt;
813 }
814
815 SamplingInfo samplingInfo;
816 if (metric.has_dimensional_sampling_info()) {
817 invalidConfigReason = handleMetricWithDimensionalSampling(
818 metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
819 if (invalidConfigReason.has_value()) {
820 return nullopt;
821 }
822 metricProducer->setSamplingInfo(samplingInfo);
823 }
824
825 invalidConfigReason = setUidFieldsIfNecessary(metric, metricProducer);
826 if (invalidConfigReason.has_value()) {
827 return nullopt;
828 }
829
830 return metricProducer;
831 }
832
createEventMetricProducerAndUpdateMetadata(const ConfigKey & key,const StatsdConfig & config,const int64_t timeBaseNs,const EventMetric & metric,const int metricIndex,const vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,const unordered_map<int64_t,int> & atomMatchingTrackerMap,vector<sp<ConditionTracker>> & allConditionTrackers,const unordered_map<int64_t,int> & conditionTrackerMap,const vector<ConditionState> & initialConditionCache,const sp<ConditionWizard> & wizard,const unordered_map<int64_t,int> & metricToActivationMap,unordered_map<int,vector<int>> & trackerToMetricMap,unordered_map<int,vector<int>> & conditionToMetricMap,unordered_map<int,vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation,optional<InvalidConfigReason> & invalidConfigReason,const wp<ConfigMetadataProvider> configMetadataProvider)833 optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
834 const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
835 const EventMetric& metric, const int metricIndex,
836 const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
837 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
838 vector<sp<ConditionTracker>>& allConditionTrackers,
839 const unordered_map<int64_t, int>& conditionTrackerMap,
840 const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
841 const unordered_map<int64_t, int>& metricToActivationMap,
842 unordered_map<int, vector<int>>& trackerToMetricMap,
843 unordered_map<int, vector<int>>& conditionToMetricMap,
844 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
845 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
846 vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason,
847 const wp<ConfigMetadataProvider> configMetadataProvider) {
848 if (!metric.has_id() || !metric.has_what()) {
849 ALOGE("cannot find the metric name or what in config");
850 invalidConfigReason =
851 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
852 return nullopt;
853 }
854 int trackerIndex;
855 invalidConfigReason = handleMetricWithAtomMatchingTrackers(
856 metric.what(), metric.id(), metricIndex, false, allAtomMatchingTrackers,
857 atomMatchingTrackerMap, trackerToMetricMap, trackerIndex);
858 if (invalidConfigReason.has_value()) {
859 return nullopt;
860 }
861
862 int conditionIndex = -1;
863 if (metric.has_condition()) {
864 invalidConfigReason = handleMetricWithConditions(
865 metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
866 allConditionTrackers, conditionIndex, conditionToMetricMap);
867 if (invalidConfigReason.has_value()) {
868 return nullopt;
869 }
870 } else {
871 if (metric.links_size() > 0) {
872 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
873 invalidConfigReason = InvalidConfigReason(
874 INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
875 return nullopt;
876 }
877 }
878
879 if (metric.sampling_percentage() < 1 || metric.sampling_percentage() > 100) {
880 invalidConfigReason = InvalidConfigReason(
881 INVALID_CONFIG_REASON_METRIC_INCORRECT_SAMPLING_PERCENTAGE, metric.id());
882 return nullopt;
883 }
884
885 unordered_map<int, shared_ptr<Activation>> eventActivationMap;
886 unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
887 invalidConfigReason = handleMetricActivation(
888 config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
889 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
890 metricsWithActivation, eventActivationMap, eventDeactivationMap);
891 if (invalidConfigReason.has_value()) return nullptr;
892
893 uint64_t metricHash;
894 invalidConfigReason =
895 getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
896 if (invalidConfigReason.has_value()) {
897 return nullopt;
898 }
899
900 sp<MetricProducer> metricProducer;
901 if (config.has_restricted_metrics_delegate_package_name()) {
902 metricProducer = new RestrictedEventMetricProducer(
903 key, metric, conditionIndex, initialConditionCache, wizard, metricHash, timeBaseNs,
904 configMetadataProvider, eventActivationMap, eventDeactivationMap);
905 } else {
906 metricProducer = new EventMetricProducer(
907 key, metric, conditionIndex, initialConditionCache, wizard, metricHash, timeBaseNs,
908 configMetadataProvider, eventActivationMap, eventDeactivationMap);
909 }
910
911 invalidConfigReason = setUidFieldsIfNecessary(metric, metricProducer);
912 if (invalidConfigReason.has_value()) {
913 return nullopt;
914 }
915
916 return metricProducer;
917 }
918
919 namespace { // anonymous namespace
hasClientAggregatedBins(const ValueMetric & metric,int binConfigIndex)920 bool hasClientAggregatedBins(const ValueMetric& metric, int binConfigIndex) {
921 return metric.histogram_bin_configs_size() > binConfigIndex &&
922 metric.histogram_bin_configs(binConfigIndex).has_client_aggregated_bins();
923 }
924
validatePositionAllInValueFields(const ValueMetric & metric,int binConfigIndex,ValueMetric::AggregationType aggType,vector<Matcher>::iterator matchersStartIt,const vector<Matcher>::iterator & matchersEndIt)925 optional<InvalidConfigReason> validatePositionAllInValueFields(
926 const ValueMetric& metric, int binConfigIndex, ValueMetric::AggregationType aggType,
927 vector<Matcher>::iterator matchersStartIt, const vector<Matcher>::iterator& matchersEndIt) {
928 if (aggType == ValueMetric::HISTOGRAM && hasClientAggregatedBins(metric, binConfigIndex)) {
929 while (matchersStartIt != matchersEndIt) {
930 if (!matchersStartIt->hasAllPositionMatcher()) {
931 ALOGE("value_field requires position ALL for client-aggregated histograms. "
932 "ValueMetric \"%lld\"",
933 (long long)metric.id());
934 return InvalidConfigReason(
935 INVALID_CONFIG_REASON_VALUE_METRIC_HIST_CLIENT_AGGREGATED_NO_POSITION_ALL,
936 metric.id());
937 }
938 matchersStartIt++;
939 }
940 return nullopt;
941 }
942 while (matchersStartIt != matchersEndIt) {
943 if (matchersStartIt->hasAllPositionMatcher()) {
944 ALOGE("value_field with position ALL is only supported for client-aggregated "
945 "histograms. ValueMetric \"%lld\"",
946 (long long)metric.id());
947 return InvalidConfigReason(
948 INVALID_CONFIG_REASON_VALUE_METRIC_VALUE_FIELD_HAS_POSITION_ALL, metric.id());
949 }
950 matchersStartIt++;
951 }
952 return nullopt;
953 }
954 } // anonymous namespace
955
createNumericValueMetricProducerAndUpdateMetadata(const ConfigKey & key,const StatsdConfig & config,const int64_t timeBaseNs,const int64_t currentTimeNs,const sp<StatsPullerManager> & pullerManager,const ValueMetric & metric,const int metricIndex,const vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,const unordered_map<int64_t,int> & atomMatchingTrackerMap,vector<sp<ConditionTracker>> & allConditionTrackers,const unordered_map<int64_t,int> & conditionTrackerMap,const vector<ConditionState> & initialConditionCache,const sp<ConditionWizard> & wizard,const sp<EventMatcherWizard> & matcherWizard,const unordered_map<int64_t,int> & stateAtomIdMap,const unordered_map<int64_t,unordered_map<int,int64_t>> & allStateGroupMaps,const unordered_map<int64_t,int> & metricToActivationMap,unordered_map<int,vector<int>> & trackerToMetricMap,unordered_map<int,vector<int>> & conditionToMetricMap,unordered_map<int,vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation,optional<InvalidConfigReason> & invalidConfigReason,const wp<ConfigMetadataProvider> configMetadataProvider)956 optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata(
957 const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
958 const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
959 const ValueMetric& metric, const int metricIndex,
960 const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
961 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
962 vector<sp<ConditionTracker>>& allConditionTrackers,
963 const unordered_map<int64_t, int>& conditionTrackerMap,
964 const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
965 const sp<EventMatcherWizard>& matcherWizard,
966 const unordered_map<int64_t, int>& stateAtomIdMap,
967 const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
968 const unordered_map<int64_t, int>& metricToActivationMap,
969 unordered_map<int, vector<int>>& trackerToMetricMap,
970 unordered_map<int, vector<int>>& conditionToMetricMap,
971 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
972 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
973 vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason,
974 const wp<ConfigMetadataProvider> configMetadataProvider) {
975 if (!metric.has_id() || !metric.has_what()) {
976 ALOGE("cannot find metric id or \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
977 invalidConfigReason =
978 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
979 return nullopt;
980 }
981 if (!metric.has_value_field()) {
982 ALOGE("cannot find \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
983 invalidConfigReason = InvalidConfigReason(
984 INVALID_CONFIG_REASON_VALUE_METRIC_MISSING_VALUE_FIELD, metric.id());
985 return nullopt;
986 }
987 std::vector<Matcher> fieldMatchers;
988 translateFieldMatcher(metric.value_field(), &fieldMatchers);
989 if (fieldMatchers.size() < 1) {
990 ALOGE("incorrect \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
991 invalidConfigReason = InvalidConfigReason(
992 INVALID_CONFIG_REASON_VALUE_METRIC_HAS_INCORRECT_VALUE_FIELD, metric.id());
993 return nullopt;
994 }
995
996 std::vector<ValueMetric::AggregationType> aggregationTypes;
997 int histogramCount = 0;
998 if (!metric.aggregation_types().empty()) {
999 if (metric.has_aggregation_type()) {
1000 invalidConfigReason = InvalidConfigReason(
1001 INVALID_CONFIG_REASON_VALUE_METRIC_DEFINES_SINGLE_AND_MULTIPLE_AGG_TYPES,
1002 metric.id());
1003 return nullopt;
1004 }
1005 if (metric.aggregation_types_size() != (int)fieldMatchers.size()) {
1006 invalidConfigReason = InvalidConfigReason(
1007 INVALID_CONFIG_REASON_VALUE_METRIC_AGG_TYPES_DNE_VALUE_FIELDS_SIZE,
1008 metric.id());
1009 return nullopt;
1010 }
1011 for (int i = 0; i < metric.aggregation_types_size(); i++) {
1012 const ValueMetric::AggregationType aggType = metric.aggregation_types(i);
1013 aggregationTypes.push_back(aggType);
1014 if (aggType == ValueMetric::HISTOGRAM) {
1015 histogramCount++;
1016 }
1017 invalidConfigReason = validatePositionAllInValueFields(
1018 metric, histogramCount - 1, aggType, fieldMatchers.begin() + i,
1019 fieldMatchers.begin() + i + 1);
1020 if (invalidConfigReason != nullopt) {
1021 return nullopt;
1022 }
1023 }
1024 } else { // aggregation_type() is set or default is used.
1025 const ValueMetric::AggregationType aggType = metric.aggregation_type();
1026 aggregationTypes.push_back(aggType);
1027 if (aggType == ValueMetric::HISTOGRAM) {
1028 histogramCount = 1;
1029 }
1030 invalidConfigReason = validatePositionAllInValueFields(
1031 metric, 0, aggType, fieldMatchers.begin(), fieldMatchers.end());
1032 if (invalidConfigReason != nullopt) {
1033 return nullopt;
1034 }
1035 }
1036
1037 if (metric.histogram_bin_configs_size() != histogramCount) {
1038 ALOGE("%d histogram aggregations specified but there are %d histogram_bin_configs",
1039 histogramCount, metric.histogram_bin_configs_size());
1040 invalidConfigReason = InvalidConfigReason(
1041 INVALID_CONFIG_REASON_VALUE_METRIC_HIST_COUNT_DNE_HIST_BIN_CONFIGS_COUNT,
1042 metric.id());
1043 return nullopt;
1044 }
1045
1046 if (aggregationTypes.front() == ValueMetric::HISTOGRAM && metric.has_threshold()) {
1047 invalidConfigReason = InvalidConfigReason(
1048 INVALID_CONFIG_REASON_VALUE_METRIC_HIST_WITH_UPLOAD_THRESHOLD, metric.id());
1049 return nullopt;
1050 }
1051
1052 if (histogramCount > 0 && metric.has_value_direction() &&
1053 metric.value_direction() != ValueMetric::INCREASING) {
1054 invalidConfigReason = InvalidConfigReason(
1055 INVALID_CONFIG_REASON_VALUE_METRIC_HIST_INVALID_VALUE_DIRECTION, metric.id());
1056 return nullopt;
1057 }
1058
1059 ParseHistogramBinConfigsResult parseBinConfigsResult =
1060 parseHistogramBinConfigs(metric, aggregationTypes);
1061 if (std::holds_alternative<InvalidConfigReason>(parseBinConfigsResult)) {
1062 invalidConfigReason = std::get<InvalidConfigReason>(parseBinConfigsResult);
1063 return nullopt;
1064 }
1065
1066 int trackerIndex;
1067 invalidConfigReason = handleMetricWithAtomMatchingTrackers(
1068 metric.what(), metric.id(), metricIndex,
1069 /*enforceOneAtom=*/true, allAtomMatchingTrackers, atomMatchingTrackerMap,
1070 trackerToMetricMap, trackerIndex);
1071 if (invalidConfigReason.has_value()) {
1072 return nullopt;
1073 }
1074
1075 const sp<AtomMatchingTracker>& atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
1076 int atomTagId = *(atomMatcher->getAtomIds().begin());
1077 int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1;
1078
1079 int conditionIndex = -1;
1080 if (metric.has_condition()) {
1081 invalidConfigReason = handleMetricWithConditions(
1082 metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
1083 allConditionTrackers, conditionIndex, conditionToMetricMap);
1084 if (invalidConfigReason.has_value()) {
1085 return nullopt;
1086 }
1087 } else if (metric.links_size() > 0) {
1088 ALOGE("metrics has a MetricConditionLink but doesn't have a condition");
1089 invalidConfigReason = InvalidConfigReason(
1090 INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
1091 return nullopt;
1092 }
1093
1094 std::vector<int> slicedStateAtoms;
1095 unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
1096 if (metric.slice_by_state_size() > 0) {
1097 invalidConfigReason =
1098 handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
1099 allStateGroupMaps, slicedStateAtoms, stateGroupMap);
1100 if (invalidConfigReason.has_value()) {
1101 return nullopt;
1102 }
1103 } else if (metric.state_link_size() > 0) {
1104 ALOGE("ValueMetric has a MetricStateLink but doesn't have a sliced state");
1105 invalidConfigReason =
1106 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
1107 return nullopt;
1108 }
1109
1110 // Check that all metric state links are a subset of dimensions_in_what fields.
1111 std::vector<Matcher> dimensionsInWhat;
1112 translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
1113 for (const auto& stateLink : metric.state_link()) {
1114 invalidConfigReason = handleMetricWithStateLink(metric.id(), stateLink.fields_in_what(),
1115 dimensionsInWhat);
1116 if (invalidConfigReason.has_value()) {
1117 ALOGW("ValueMetric's MetricStateLinks must be a subset of the dimensions in what");
1118 return nullopt;
1119 }
1120 }
1121
1122 unordered_map<int, shared_ptr<Activation>> eventActivationMap;
1123 unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
1124 invalidConfigReason = handleMetricActivation(
1125 config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
1126 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1127 metricsWithActivation, eventActivationMap, eventDeactivationMap);
1128 if (invalidConfigReason.has_value()) {
1129 return nullopt;
1130 }
1131
1132 uint64_t metricHash;
1133 invalidConfigReason =
1134 getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
1135 if (invalidConfigReason.has_value()) {
1136 return nullopt;
1137 }
1138
1139 const TimeUnit bucketSizeTimeUnit =
1140 metric.bucket() == TIME_UNIT_UNSPECIFIED ? ONE_HOUR : metric.bucket();
1141 const int64_t bucketSizeNs =
1142 MillisToNano(TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), bucketSizeTimeUnit));
1143
1144 const bool containsAnyPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what());
1145 const bool shouldUseNestedDimensions = ShouldUseNestedDimensions(metric.dimensions_in_what());
1146
1147 const auto [dimensionSoftLimit, dimensionHardLimit] =
1148 StatsdStats::getAtomDimensionKeySizeLimits(
1149 pullTagId,
1150 StatsdStats::clampDimensionKeySizeLimit(metric.max_dimensions_per_bucket()));
1151
1152 // get the condition_correction_threshold_nanos value
1153 const optional<int64_t> conditionCorrectionThresholdNs =
1154 metric.has_condition_correction_threshold_nanos()
1155 ? optional<int64_t>(metric.condition_correction_threshold_nanos())
1156 : nullopt;
1157
1158 const vector<optional<const BinStarts>>& binStartsList =
1159 std::get<vector<optional<const BinStarts>>>(parseBinConfigsResult);
1160 sp<MetricProducer> metricProducer = new NumericValueMetricProducer(
1161 key, metric, metricHash, {pullTagId, pullerManager},
1162 {timeBaseNs, currentTimeNs, bucketSizeNs, metric.min_bucket_size_nanos(),
1163 conditionCorrectionThresholdNs, getAppUpgradeBucketSplit(metric)},
1164 {containsAnyPositionInDimensionsInWhat, shouldUseNestedDimensions, trackerIndex,
1165 matcherWizard, metric.dimensions_in_what(), fieldMatchers, aggregationTypes,
1166 binStartsList},
1167 {conditionIndex, metric.links(), initialConditionCache, wizard},
1168 {metric.state_link(), slicedStateAtoms, stateGroupMap},
1169 {eventActivationMap, eventDeactivationMap}, {dimensionSoftLimit, dimensionHardLimit},
1170 configMetadataProvider);
1171
1172 SamplingInfo samplingInfo;
1173 if (metric.has_dimensional_sampling_info()) {
1174 invalidConfigReason = handleMetricWithDimensionalSampling(
1175 metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
1176 if (invalidConfigReason.has_value()) {
1177 return nullopt;
1178 }
1179 metricProducer->setSamplingInfo(samplingInfo);
1180 }
1181
1182 invalidConfigReason = setUidFieldsIfNecessary(metric, metricProducer);
1183 if (invalidConfigReason.has_value()) {
1184 return nullopt;
1185 }
1186
1187 return metricProducer;
1188 }
1189
createKllMetricProducerAndUpdateMetadata(const ConfigKey & key,const StatsdConfig & config,const int64_t timeBaseNs,const int64_t currentTimeNs,const sp<StatsPullerManager> & pullerManager,const KllMetric & metric,const int metricIndex,const vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,const unordered_map<int64_t,int> & atomMatchingTrackerMap,vector<sp<ConditionTracker>> & allConditionTrackers,const unordered_map<int64_t,int> & conditionTrackerMap,const vector<ConditionState> & initialConditionCache,const sp<ConditionWizard> & wizard,const sp<EventMatcherWizard> & matcherWizard,const unordered_map<int64_t,int> & stateAtomIdMap,const unordered_map<int64_t,unordered_map<int,int64_t>> & allStateGroupMaps,const unordered_map<int64_t,int> & metricToActivationMap,unordered_map<int,vector<int>> & trackerToMetricMap,unordered_map<int,vector<int>> & conditionToMetricMap,unordered_map<int,vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation,optional<InvalidConfigReason> & invalidConfigReason,const wp<ConfigMetadataProvider> configMetadataProvider)1190 optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata(
1191 const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
1192 const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
1193 const KllMetric& metric, const int metricIndex,
1194 const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
1195 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
1196 vector<sp<ConditionTracker>>& allConditionTrackers,
1197 const unordered_map<int64_t, int>& conditionTrackerMap,
1198 const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
1199 const sp<EventMatcherWizard>& matcherWizard,
1200 const unordered_map<int64_t, int>& stateAtomIdMap,
1201 const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
1202 const unordered_map<int64_t, int>& metricToActivationMap,
1203 unordered_map<int, vector<int>>& trackerToMetricMap,
1204 unordered_map<int, vector<int>>& conditionToMetricMap,
1205 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
1206 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
1207 vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason,
1208 const wp<ConfigMetadataProvider> configMetadataProvider) {
1209 if (!metric.has_id() || !metric.has_what()) {
1210 ALOGE("cannot find metric id or \"what\" in KllMetric \"%lld\"", (long long)metric.id());
1211 invalidConfigReason =
1212 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
1213 return nullopt;
1214 }
1215 if (!metric.has_kll_field()) {
1216 ALOGE("cannot find \"kll_field\" in KllMetric \"%lld\"", (long long)metric.id());
1217 invalidConfigReason = InvalidConfigReason(
1218 INVALID_CONFIG_REASON_KLL_METRIC_MISSING_KLL_FIELD, metric.id());
1219 return nullopt;
1220 }
1221 if (HasPositionALL(metric.kll_field())) {
1222 ALOGE("kll field with position ALL is not supported. KllMetric \"%lld\"",
1223 (long long)metric.id());
1224 invalidConfigReason = InvalidConfigReason(
1225 INVALID_CONFIG_REASON_KLL_METRIC_KLL_FIELD_HAS_POSITION_ALL, metric.id());
1226 return nullopt;
1227 }
1228 std::vector<Matcher> fieldMatchers;
1229 translateFieldMatcher(metric.kll_field(), &fieldMatchers);
1230 if (fieldMatchers.empty()) {
1231 ALOGE("incorrect \"kll_field\" in KllMetric \"%lld\"", (long long)metric.id());
1232 invalidConfigReason = InvalidConfigReason(
1233 INVALID_CONFIG_REASON_KLL_METRIC_HAS_INCORRECT_KLL_FIELD, metric.id());
1234 return nullopt;
1235 }
1236
1237 int trackerIndex;
1238 invalidConfigReason = handleMetricWithAtomMatchingTrackers(
1239 metric.what(), metric.id(), metricIndex,
1240 /*enforceOneAtom=*/true, allAtomMatchingTrackers, atomMatchingTrackerMap,
1241 trackerToMetricMap, trackerIndex);
1242 if (invalidConfigReason.has_value()) {
1243 return nullopt;
1244 }
1245
1246 int conditionIndex = -1;
1247 if (metric.has_condition()) {
1248 invalidConfigReason = handleMetricWithConditions(
1249 metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
1250 allConditionTrackers, conditionIndex, conditionToMetricMap);
1251 if (invalidConfigReason.has_value()) {
1252 return nullopt;
1253 }
1254 } else if (metric.links_size() > 0) {
1255 ALOGE("metrics has a MetricConditionLink but doesn't have a condition");
1256 invalidConfigReason = InvalidConfigReason(
1257 INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
1258 return nullopt;
1259 }
1260
1261 std::vector<int> slicedStateAtoms;
1262 unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
1263 if (metric.slice_by_state_size() > 0) {
1264 invalidConfigReason =
1265 handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
1266 allStateGroupMaps, slicedStateAtoms, stateGroupMap);
1267 if (invalidConfigReason.has_value()) {
1268 return nullopt;
1269 }
1270 } else if (metric.state_link_size() > 0) {
1271 ALOGE("KllMetric has a MetricStateLink but doesn't have a sliced state");
1272 invalidConfigReason =
1273 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
1274 return nullopt;
1275 }
1276
1277 // Check that all metric state links are a subset of dimensions_in_what fields.
1278 std::vector<Matcher> dimensionsInWhat;
1279 translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
1280 for (const auto& stateLink : metric.state_link()) {
1281 invalidConfigReason = handleMetricWithStateLink(metric.id(), stateLink.fields_in_what(),
1282 dimensionsInWhat);
1283 if (invalidConfigReason.has_value()) {
1284 ALOGW("KllMetric's MetricStateLinks must be a subset of the dimensions in what");
1285 return nullopt;
1286 }
1287 }
1288
1289 unordered_map<int, shared_ptr<Activation>> eventActivationMap;
1290 unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
1291 invalidConfigReason = handleMetricActivation(
1292 config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
1293 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1294 metricsWithActivation, eventActivationMap, eventDeactivationMap);
1295 if (invalidConfigReason.has_value()) {
1296 return nullopt;
1297 }
1298
1299 uint64_t metricHash;
1300 invalidConfigReason =
1301 getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
1302 if (invalidConfigReason.has_value()) {
1303 return nullopt;
1304 }
1305
1306 const TimeUnit bucketSizeTimeUnit =
1307 metric.bucket() == TIME_UNIT_UNSPECIFIED ? ONE_HOUR : metric.bucket();
1308 const int64_t bucketSizeNs =
1309 MillisToNano(TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), bucketSizeTimeUnit));
1310
1311 const bool containsAnyPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what());
1312 const bool shouldUseNestedDimensions = ShouldUseNestedDimensions(metric.dimensions_in_what());
1313
1314 const sp<AtomMatchingTracker>& atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
1315 const int atomTagId = *(atomMatcher->getAtomIds().begin());
1316 const auto [dimensionSoftLimit, dimensionHardLimit] =
1317 StatsdStats::getAtomDimensionKeySizeLimits(
1318 atomTagId,
1319 StatsdStats::clampDimensionKeySizeLimit(metric.max_dimensions_per_bucket()));
1320
1321 sp<MetricProducer> metricProducer = new KllMetricProducer(
1322 key, metric, metricHash, {/*pullTagId=*/-1, pullerManager},
1323 {timeBaseNs, currentTimeNs, bucketSizeNs, metric.min_bucket_size_nanos(),
1324 /*conditionCorrectionThresholdNs=*/nullopt, getAppUpgradeBucketSplit(metric)},
1325 {containsAnyPositionInDimensionsInWhat,
1326 shouldUseNestedDimensions,
1327 trackerIndex,
1328 matcherWizard,
1329 metric.dimensions_in_what(),
1330 fieldMatchers,
1331 {}},
1332 {conditionIndex, metric.links(), initialConditionCache, wizard},
1333 {metric.state_link(), slicedStateAtoms, stateGroupMap},
1334 {eventActivationMap, eventDeactivationMap}, {dimensionSoftLimit, dimensionHardLimit},
1335 configMetadataProvider);
1336
1337 SamplingInfo samplingInfo;
1338 if (metric.has_dimensional_sampling_info()) {
1339 invalidConfigReason = handleMetricWithDimensionalSampling(
1340 metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
1341 if (invalidConfigReason.has_value()) {
1342 return nullopt;
1343 }
1344 metricProducer->setSamplingInfo(samplingInfo);
1345 }
1346
1347 invalidConfigReason = setUidFieldsIfNecessary(metric, metricProducer);
1348 if (invalidConfigReason.has_value()) {
1349 return nullopt;
1350 }
1351
1352 return metricProducer;
1353 }
1354
createGaugeMetricProducerAndUpdateMetadata(const ConfigKey & key,const StatsdConfig & config,const int64_t timeBaseNs,const int64_t currentTimeNs,const sp<StatsPullerManager> & pullerManager,const GaugeMetric & metric,const int metricIndex,const vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,const unordered_map<int64_t,int> & atomMatchingTrackerMap,vector<sp<ConditionTracker>> & allConditionTrackers,const unordered_map<int64_t,int> & conditionTrackerMap,const vector<ConditionState> & initialConditionCache,const sp<ConditionWizard> & wizard,const sp<EventMatcherWizard> & matcherWizard,const unordered_map<int64_t,int> & metricToActivationMap,unordered_map<int,vector<int>> & trackerToMetricMap,unordered_map<int,vector<int>> & conditionToMetricMap,unordered_map<int,vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation,optional<InvalidConfigReason> & invalidConfigReason,const wp<ConfigMetadataProvider> configMetadataProvider)1355 optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
1356 const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
1357 const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
1358 const GaugeMetric& metric, const int metricIndex,
1359 const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
1360 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
1361 vector<sp<ConditionTracker>>& allConditionTrackers,
1362 const unordered_map<int64_t, int>& conditionTrackerMap,
1363 const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
1364 const sp<EventMatcherWizard>& matcherWizard,
1365 const unordered_map<int64_t, int>& metricToActivationMap,
1366 unordered_map<int, vector<int>>& trackerToMetricMap,
1367 unordered_map<int, vector<int>>& conditionToMetricMap,
1368 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
1369 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
1370 vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason,
1371 const wp<ConfigMetadataProvider> configMetadataProvider) {
1372 if (!metric.has_id() || !metric.has_what()) {
1373 ALOGE("cannot find metric id or \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
1374 invalidConfigReason =
1375 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
1376 return nullopt;
1377 }
1378
1379 if ((!metric.gauge_fields_filter().has_include_all() ||
1380 (metric.gauge_fields_filter().include_all() == false)) &&
1381 !hasLeafNode(metric.gauge_fields_filter().fields())) {
1382 ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
1383 invalidConfigReason = InvalidConfigReason(
1384 INVALID_CONFIG_REASON_GAUGE_METRIC_INCORRECT_FIELD_FILTER, metric.id());
1385 return nullopt;
1386 }
1387 if ((metric.gauge_fields_filter().has_include_all() &&
1388 metric.gauge_fields_filter().include_all() == true) &&
1389 hasLeafNode(metric.gauge_fields_filter().fields())) {
1390 ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
1391 invalidConfigReason = InvalidConfigReason(
1392 INVALID_CONFIG_REASON_GAUGE_METRIC_INCORRECT_FIELD_FILTER, metric.id());
1393 return nullopt;
1394 }
1395
1396 int trackerIndex;
1397 invalidConfigReason = handleMetricWithAtomMatchingTrackers(
1398 metric.what(), metric.id(), metricIndex, true, allAtomMatchingTrackers,
1399 atomMatchingTrackerMap, trackerToMetricMap, trackerIndex);
1400 if (invalidConfigReason.has_value()) {
1401 return nullopt;
1402 }
1403
1404 const sp<AtomMatchingTracker>& atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
1405 int atomTagId = *(atomMatcher->getAtomIds().begin());
1406 int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1;
1407
1408 int triggerTrackerIndex;
1409 int triggerAtomId = -1;
1410 if (metric.has_trigger_event()) {
1411 if (pullTagId == -1) {
1412 ALOGW("Pull atom not specified for trigger");
1413 invalidConfigReason = InvalidConfigReason(
1414 INVALID_CONFIG_REASON_GAUGE_METRIC_TRIGGER_NO_PULL_ATOM, metric.id());
1415 return nullopt;
1416 }
1417 // trigger_event should be used with FIRST_N_SAMPLES
1418 if (metric.sampling_type() != GaugeMetric::FIRST_N_SAMPLES) {
1419 ALOGW("Gauge Metric with trigger event must have sampling type FIRST_N_SAMPLES");
1420 invalidConfigReason = InvalidConfigReason(
1421 INVALID_CONFIG_REASON_GAUGE_METRIC_TRIGGER_NO_FIRST_N_SAMPLES, metric.id());
1422 return nullopt;
1423 }
1424 invalidConfigReason = handleMetricWithAtomMatchingTrackers(
1425 metric.trigger_event(), metric.id(), metricIndex,
1426 /*enforceOneAtom=*/true, allAtomMatchingTrackers, atomMatchingTrackerMap,
1427 trackerToMetricMap, triggerTrackerIndex);
1428 if (invalidConfigReason.has_value()) {
1429 return nullopt;
1430 }
1431 const sp<AtomMatchingTracker>& triggerAtomMatcher =
1432 allAtomMatchingTrackers.at(triggerTrackerIndex);
1433 triggerAtomId = *(triggerAtomMatcher->getAtomIds().begin());
1434 }
1435
1436 int conditionIndex = -1;
1437 if (metric.has_condition()) {
1438 invalidConfigReason = handleMetricWithConditions(
1439 metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
1440 allConditionTrackers, conditionIndex, conditionToMetricMap);
1441 if (invalidConfigReason.has_value()) {
1442 return nullopt;
1443 }
1444 } else {
1445 if (metric.links_size() > 0) {
1446 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
1447 invalidConfigReason = InvalidConfigReason(
1448 INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
1449 return nullopt;
1450 }
1451 }
1452
1453 if (pullTagId != -1 && metric.sampling_percentage() != 100) {
1454 invalidConfigReason = InvalidConfigReason(
1455 INVALID_CONFIG_REASON_GAUGE_METRIC_PULLED_WITH_SAMPLING, metric.id());
1456 return nullopt;
1457 }
1458
1459 if (metric.sampling_percentage() < 1 || metric.sampling_percentage() > 100) {
1460 invalidConfigReason = InvalidConfigReason(
1461 INVALID_CONFIG_REASON_METRIC_INCORRECT_SAMPLING_PERCENTAGE, metric.id());
1462 return nullopt;
1463 }
1464
1465 if (metric.pull_probability() < 1 || metric.pull_probability() > 100) {
1466 invalidConfigReason = InvalidConfigReason(
1467 INVALID_CONFIG_REASON_METRIC_INCORRECT_PULL_PROBABILITY, metric.id());
1468 return nullopt;
1469 }
1470
1471 if (metric.pull_probability() != 100) {
1472 if (pullTagId == -1) {
1473 invalidConfigReason = InvalidConfigReason(
1474 INVALID_CONFIG_REASON_GAUGE_METRIC_PUSHED_WITH_PULL_PROBABILITY, metric.id());
1475 return nullopt;
1476 }
1477 if (metric.sampling_type() == GaugeMetric::RANDOM_ONE_SAMPLE) {
1478 invalidConfigReason = InvalidConfigReason(
1479 INVALID_CONFIG_REASON_GAUGE_METRIC_RANDOM_ONE_SAMPLE_WITH_PULL_PROBABILITY,
1480 metric.id());
1481 return nullopt;
1482 }
1483 }
1484
1485 unordered_map<int, shared_ptr<Activation>> eventActivationMap;
1486 unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
1487 invalidConfigReason = handleMetricActivation(
1488 config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
1489 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1490 metricsWithActivation, eventActivationMap, eventDeactivationMap);
1491 if (invalidConfigReason.has_value()) {
1492 return nullopt;
1493 }
1494
1495 uint64_t metricHash;
1496 invalidConfigReason =
1497 getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
1498 if (invalidConfigReason.has_value()) {
1499 return nullopt;
1500 }
1501
1502 const auto [dimensionSoftLimit, dimensionHardLimit] =
1503 StatsdStats::getAtomDimensionKeySizeLimits(
1504 pullTagId,
1505 StatsdStats::clampDimensionKeySizeLimit(metric.max_dimensions_per_bucket()));
1506
1507 sp<MetricProducer> metricProducer = new GaugeMetricProducer(
1508 key, metric, conditionIndex, initialConditionCache, wizard, metricHash, trackerIndex,
1509 matcherWizard, pullTagId, triggerAtomId, atomTagId, timeBaseNs, currentTimeNs,
1510 pullerManager, configMetadataProvider, eventActivationMap, eventDeactivationMap,
1511 dimensionSoftLimit, dimensionHardLimit);
1512
1513 SamplingInfo samplingInfo;
1514 std::vector<Matcher> dimensionsInWhat;
1515 translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
1516 if (metric.has_dimensional_sampling_info()) {
1517 invalidConfigReason = handleMetricWithDimensionalSampling(
1518 metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
1519 if (invalidConfigReason.has_value()) {
1520 return nullopt;
1521 }
1522 metricProducer->setSamplingInfo(samplingInfo);
1523 }
1524
1525 invalidConfigReason = setUidFieldsIfNecessary(metric, metricProducer);
1526 if (invalidConfigReason.has_value()) {
1527 return nullopt;
1528 }
1529
1530 return metricProducer;
1531 }
1532
createAnomalyTracker(const Alert & alert,const sp<AlarmMonitor> & anomalyAlarmMonitor,const UpdateStatus & updateStatus,const int64_t currentTimeNs,const unordered_map<int64_t,int> & metricProducerMap,vector<sp<MetricProducer>> & allMetricProducers,optional<InvalidConfigReason> & invalidConfigReason)1533 optional<sp<AnomalyTracker>> createAnomalyTracker(
1534 const Alert& alert, const sp<AlarmMonitor>& anomalyAlarmMonitor,
1535 const UpdateStatus& updateStatus, const int64_t currentTimeNs,
1536 const unordered_map<int64_t, int>& metricProducerMap,
1537 vector<sp<MetricProducer>>& allMetricProducers,
1538 optional<InvalidConfigReason>& invalidConfigReason) {
1539 const auto& itr = metricProducerMap.find(alert.metric_id());
1540 if (itr == metricProducerMap.end()) {
1541 ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
1542 (long long)alert.metric_id());
1543 invalidConfigReason = createInvalidConfigReasonWithAlert(
1544 INVALID_CONFIG_REASON_ALERT_METRIC_NOT_FOUND, alert.metric_id(), alert.id());
1545 return nullopt;
1546 }
1547 if (!alert.has_trigger_if_sum_gt()) {
1548 ALOGW("invalid alert: missing threshold");
1549 invalidConfigReason = createInvalidConfigReasonWithAlert(
1550 INVALID_CONFIG_REASON_ALERT_THRESHOLD_MISSING, alert.id());
1551 return nullopt;
1552 }
1553 if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
1554 ALOGW("invalid alert: threshold=%f num_buckets= %d", alert.trigger_if_sum_gt(),
1555 alert.num_buckets());
1556 invalidConfigReason = createInvalidConfigReasonWithAlert(
1557 INVALID_CONFIG_REASON_ALERT_INVALID_TRIGGER_OR_NUM_BUCKETS, alert.id());
1558 return nullopt;
1559 }
1560 const int metricIndex = itr->second;
1561 sp<MetricProducer> metric = allMetricProducers[metricIndex];
1562 sp<AnomalyTracker> anomalyTracker =
1563 metric->addAnomalyTracker(alert, anomalyAlarmMonitor, updateStatus, currentTimeNs);
1564 if (anomalyTracker == nullptr) {
1565 // The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
1566 invalidConfigReason = createInvalidConfigReasonWithAlert(
1567 INVALID_CONFIG_REASON_ALERT_CANNOT_ADD_ANOMALY, alert.metric_id(), alert.id());
1568 return nullopt;
1569 }
1570 return {anomalyTracker};
1571 }
1572
initAtomMatchingTrackers(const StatsdConfig & config,const sp<UidMap> & uidMap,unordered_map<int64_t,int> & atomMatchingTrackerMap,vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,unordered_map<int,vector<int>> & allTagIdsToMatchersMap)1573 optional<InvalidConfigReason> initAtomMatchingTrackers(
1574 const StatsdConfig& config, const sp<UidMap>& uidMap,
1575 unordered_map<int64_t, int>& atomMatchingTrackerMap,
1576 vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
1577 unordered_map<int, vector<int>>& allTagIdsToMatchersMap) {
1578 vector<AtomMatcher> matcherConfigs;
1579 const int atomMatcherCount = config.atom_matcher_size();
1580 matcherConfigs.reserve(atomMatcherCount);
1581 allAtomMatchingTrackers.reserve(atomMatcherCount);
1582 optional<InvalidConfigReason> invalidConfigReason;
1583
1584 for (int i = 0; i < atomMatcherCount; i++) {
1585 const AtomMatcher& logMatcher = config.atom_matcher(i);
1586 sp<AtomMatchingTracker> tracker =
1587 createAtomMatchingTracker(logMatcher, uidMap, invalidConfigReason);
1588 if (tracker == nullptr) {
1589 return invalidConfigReason;
1590 }
1591 allAtomMatchingTrackers.push_back(tracker);
1592 if (atomMatchingTrackerMap.find(logMatcher.id()) != atomMatchingTrackerMap.end()) {
1593 ALOGE("Duplicate AtomMatcher found!");
1594 return createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_DUPLICATE,
1595 logMatcher.id());
1596 }
1597 atomMatchingTrackerMap[logMatcher.id()] = i;
1598 matcherConfigs.push_back(logMatcher);
1599 }
1600
1601 vector<uint8_t> stackTracker2(allAtomMatchingTrackers.size(), false);
1602 for (size_t matcherIndex = 0; matcherIndex < allAtomMatchingTrackers.size(); matcherIndex++) {
1603 auto& matcher = allAtomMatchingTrackers[matcherIndex];
1604 const auto [invalidConfigReason, _] =
1605 matcher->init(matcherIndex, matcherConfigs, allAtomMatchingTrackers,
1606 atomMatchingTrackerMap, stackTracker2);
1607 if (invalidConfigReason.has_value()) {
1608 return invalidConfigReason;
1609 }
1610
1611 // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
1612 const set<int>& tagIds = matcher->getAtomIds();
1613 for (int atomId : tagIds) {
1614 auto& matchers = allTagIdsToMatchersMap[atomId];
1615 // Performance note:
1616 // For small amount of elements linear search in vector will be
1617 // faster then look up in a set:
1618 // - we do not expect matchers vector per atom id will have significant size (< 10)
1619 // - iteration via vector is the fastest way compared to other containers (set, etc.)
1620 // in the hot path MetricsManager::onLogEvent()
1621 // - vector<T> will have the smallest memory footprint compared to any other
1622 // std containers implementation
1623 if (find(matchers.begin(), matchers.end(), matcherIndex) == matchers.end()) {
1624 matchers.push_back(matcherIndex);
1625 }
1626 }
1627 }
1628
1629 return nullopt;
1630 }
1631
initConditions(const ConfigKey & key,const StatsdConfig & config,const unordered_map<int64_t,int> & atomMatchingTrackerMap,unordered_map<int64_t,int> & conditionTrackerMap,vector<sp<ConditionTracker>> & allConditionTrackers,unordered_map<int,std::vector<int>> & trackerToConditionMap,vector<ConditionState> & initialConditionCache)1632 optional<InvalidConfigReason> initConditions(
1633 const ConfigKey& key, const StatsdConfig& config,
1634 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
1635 unordered_map<int64_t, int>& conditionTrackerMap,
1636 vector<sp<ConditionTracker>>& allConditionTrackers,
1637 unordered_map<int, std::vector<int>>& trackerToConditionMap,
1638 vector<ConditionState>& initialConditionCache) {
1639 vector<Predicate> conditionConfigs;
1640 const int conditionTrackerCount = config.predicate_size();
1641 conditionConfigs.reserve(conditionTrackerCount);
1642 allConditionTrackers.reserve(conditionTrackerCount);
1643 initialConditionCache.assign(conditionTrackerCount, ConditionState::kNotEvaluated);
1644 optional<InvalidConfigReason> invalidConfigReason;
1645
1646 for (int i = 0; i < conditionTrackerCount; i++) {
1647 const Predicate& condition = config.predicate(i);
1648 sp<ConditionTracker> tracker = createConditionTracker(
1649 key, condition, i, atomMatchingTrackerMap, invalidConfigReason);
1650 if (tracker == nullptr) {
1651 return invalidConfigReason;
1652 }
1653 allConditionTrackers.push_back(tracker);
1654 if (conditionTrackerMap.find(condition.id()) != conditionTrackerMap.end()) {
1655 ALOGE("Duplicate Predicate found!");
1656 return createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_CONDITION_DUPLICATE,
1657 condition.id());
1658 }
1659 conditionTrackerMap[condition.id()] = i;
1660 conditionConfigs.push_back(condition);
1661 }
1662
1663 vector<uint8_t> stackTracker(allConditionTrackers.size(), false);
1664 for (size_t i = 0; i < allConditionTrackers.size(); i++) {
1665 auto& conditionTracker = allConditionTrackers[i];
1666 invalidConfigReason =
1667 conditionTracker->init(conditionConfigs, allConditionTrackers, conditionTrackerMap,
1668 stackTracker, initialConditionCache);
1669 if (invalidConfigReason.has_value()) {
1670 return invalidConfigReason;
1671 }
1672 for (const int trackerIndex : conditionTracker->getAtomMatchingTrackerIndex()) {
1673 auto& conditionList = trackerToConditionMap[trackerIndex];
1674 conditionList.push_back(i);
1675 }
1676 }
1677 return nullopt;
1678 }
1679
initStates(const StatsdConfig & config,unordered_map<int64_t,int> & stateAtomIdMap,unordered_map<int64_t,unordered_map<int,int64_t>> & allStateGroupMaps,map<int64_t,uint64_t> & stateProtoHashes)1680 optional<InvalidConfigReason> initStates(
1681 const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
1682 unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
1683 map<int64_t, uint64_t>& stateProtoHashes) {
1684 for (int i = 0; i < config.state_size(); i++) {
1685 const State& state = config.state(i);
1686 const int64_t stateId = state.id();
1687 stateAtomIdMap[stateId] = state.atom_id();
1688
1689 string serializedState;
1690 if (!state.SerializeToString(&serializedState)) {
1691 ALOGE("Unable to serialize state %lld", (long long)stateId);
1692 return createInvalidConfigReasonWithState(
1693 INVALID_CONFIG_REASON_STATE_SERIALIZATION_FAILED, state.id(), state.atom_id());
1694 }
1695 stateProtoHashes[stateId] = Hash64(serializedState);
1696
1697 const StateMap& stateMap = state.map();
1698 for (const auto& group : stateMap.group()) {
1699 for (const auto& value : group.value()) {
1700 allStateGroupMaps[stateId][value] = group.group_id();
1701 }
1702 }
1703 }
1704
1705 return nullopt;
1706 }
1707
initMetrics(const ConfigKey & key,const StatsdConfig & config,const int64_t timeBaseTimeNs,const int64_t currentTimeNs,const sp<StatsPullerManager> & pullerManager,const unordered_map<int64_t,int> & atomMatchingTrackerMap,const unordered_map<int64_t,int> & conditionTrackerMap,const vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,const unordered_map<int64_t,int> & stateAtomIdMap,const unordered_map<int64_t,unordered_map<int,int64_t>> & allStateGroupMaps,vector<sp<ConditionTracker>> & allConditionTrackers,const vector<ConditionState> & initialConditionCache,vector<sp<MetricProducer>> & allMetricProducers,unordered_map<int,vector<int>> & conditionToMetricMap,unordered_map<int,vector<int>> & trackerToMetricMap,unordered_map<int64_t,int> & metricMap,std::set<int64_t> & noReportMetricIds,unordered_map<int,vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation,const wp<ConfigMetadataProvider> configMetadataProvider)1708 optional<InvalidConfigReason> initMetrics(
1709 const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
1710 const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
1711 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
1712 const unordered_map<int64_t, int>& conditionTrackerMap,
1713 const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
1714 const unordered_map<int64_t, int>& stateAtomIdMap,
1715 const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
1716 vector<sp<ConditionTracker>>& allConditionTrackers,
1717 const vector<ConditionState>& initialConditionCache,
1718 vector<sp<MetricProducer>>& allMetricProducers,
1719 unordered_map<int, vector<int>>& conditionToMetricMap,
1720 unordered_map<int, vector<int>>& trackerToMetricMap, unordered_map<int64_t, int>& metricMap,
1721 std::set<int64_t>& noReportMetricIds,
1722 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
1723 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
1724 vector<int>& metricsWithActivation,
1725 const wp<ConfigMetadataProvider> configMetadataProvider) {
1726 sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
1727 sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchingTrackers);
1728 const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
1729 config.event_metric_size() + config.gauge_metric_size() +
1730 config.value_metric_size() + config.kll_metric_size();
1731 allMetricProducers.reserve(allMetricsCount);
1732 optional<InvalidConfigReason> invalidConfigReason;
1733
1734 if (config.has_restricted_metrics_delegate_package_name() &&
1735 allMetricsCount != config.event_metric_size()) {
1736 ALOGE("Restricted metrics only support event metric");
1737 return InvalidConfigReason(INVALID_CONFIG_REASON_RESTRICTED_METRIC_NOT_SUPPORTED);
1738 }
1739
1740 // Construct map from metric id to metric activation index. The map will be used to determine
1741 // the metric activation corresponding to a metric.
1742 unordered_map<int64_t, int> metricToActivationMap;
1743 for (int i = 0; i < config.metric_activation_size(); i++) {
1744 const MetricActivation& metricActivation = config.metric_activation(i);
1745 int64_t metricId = metricActivation.metric_id();
1746 if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) {
1747 ALOGE("Metric %lld has multiple MetricActivations", (long long)metricId);
1748 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_HAS_MULTIPLE_ACTIVATIONS,
1749 metricId);
1750 }
1751 metricToActivationMap.insert({metricId, i});
1752 }
1753
1754 // Build MetricProducers for each metric defined in config.
1755 // build CountMetricProducer
1756 for (int i = 0; i < config.count_metric_size(); i++) {
1757 int metricIndex = allMetricProducers.size();
1758 const CountMetric& metric = config.count_metric(i);
1759 metricMap.insert({metric.id(), metricIndex});
1760 optional<sp<MetricProducer>> producer = createCountMetricProducerAndUpdateMetadata(
1761 key, config, timeBaseTimeNs, currentTimeNs, metric, metricIndex,
1762 allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
1763 conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
1764 allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
1765 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1766 metricsWithActivation, invalidConfigReason, configMetadataProvider);
1767 if (!producer) {
1768 return invalidConfigReason;
1769 }
1770 allMetricProducers.push_back(producer.value());
1771 }
1772
1773 // build DurationMetricProducer
1774 for (int i = 0; i < config.duration_metric_size(); i++) {
1775 int metricIndex = allMetricProducers.size();
1776 const DurationMetric& metric = config.duration_metric(i);
1777 metricMap.insert({metric.id(), metricIndex});
1778
1779 optional<sp<MetricProducer>> producer = createDurationMetricProducerAndUpdateMetadata(
1780 key, config, timeBaseTimeNs, currentTimeNs, metric, metricIndex,
1781 allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
1782 conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
1783 allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
1784 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1785 metricsWithActivation, invalidConfigReason, configMetadataProvider);
1786 if (!producer) {
1787 return invalidConfigReason;
1788 }
1789 allMetricProducers.push_back(producer.value());
1790 }
1791
1792 // build EventMetricProducer
1793 for (int i = 0; i < config.event_metric_size(); i++) {
1794 int metricIndex = allMetricProducers.size();
1795 const EventMetric& metric = config.event_metric(i);
1796 metricMap.insert({metric.id(), metricIndex});
1797 optional<sp<MetricProducer>> producer = createEventMetricProducerAndUpdateMetadata(
1798 key, config, timeBaseTimeNs, metric, metricIndex, allAtomMatchingTrackers,
1799 atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap,
1800 initialConditionCache, wizard, metricToActivationMap, trackerToMetricMap,
1801 conditionToMetricMap, activationAtomTrackerToMetricMap,
1802 deactivationAtomTrackerToMetricMap, metricsWithActivation, invalidConfigReason,
1803 configMetadataProvider);
1804 if (!producer) {
1805 return invalidConfigReason;
1806 }
1807 allMetricProducers.push_back(producer.value());
1808 }
1809
1810 // build NumericValueMetricProducer
1811 for (int i = 0; i < config.value_metric_size(); i++) {
1812 int metricIndex = allMetricProducers.size();
1813 const ValueMetric& metric = config.value_metric(i);
1814 metricMap.insert({metric.id(), metricIndex});
1815 optional<sp<MetricProducer>> producer = createNumericValueMetricProducerAndUpdateMetadata(
1816 key, config, timeBaseTimeNs, currentTimeNs, pullerManager, metric, metricIndex,
1817 allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
1818 conditionTrackerMap, initialConditionCache, wizard, matcherWizard, stateAtomIdMap,
1819 allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
1820 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1821 metricsWithActivation, invalidConfigReason, configMetadataProvider);
1822 if (!producer) {
1823 return invalidConfigReason;
1824 }
1825 allMetricProducers.push_back(producer.value());
1826 }
1827
1828 // build KllMetricProducer
1829 for (int i = 0; i < config.kll_metric_size(); i++) {
1830 int metricIndex = allMetricProducers.size();
1831 const KllMetric& metric = config.kll_metric(i);
1832 metricMap.insert({metric.id(), metricIndex});
1833 optional<sp<MetricProducer>> producer = createKllMetricProducerAndUpdateMetadata(
1834 key, config, timeBaseTimeNs, currentTimeNs, pullerManager, metric, metricIndex,
1835 allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
1836 conditionTrackerMap, initialConditionCache, wizard, matcherWizard, stateAtomIdMap,
1837 allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
1838 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1839 metricsWithActivation, invalidConfigReason, configMetadataProvider);
1840 if (!producer) {
1841 return invalidConfigReason;
1842 }
1843 allMetricProducers.push_back(producer.value());
1844 }
1845
1846 // Gauge metrics.
1847 for (int i = 0; i < config.gauge_metric_size(); i++) {
1848 int metricIndex = allMetricProducers.size();
1849 const GaugeMetric& metric = config.gauge_metric(i);
1850 metricMap.insert({metric.id(), metricIndex});
1851 optional<sp<MetricProducer>> producer = createGaugeMetricProducerAndUpdateMetadata(
1852 key, config, timeBaseTimeNs, currentTimeNs, pullerManager, metric, metricIndex,
1853 allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
1854 conditionTrackerMap, initialConditionCache, wizard, matcherWizard,
1855 metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
1856 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1857 metricsWithActivation, invalidConfigReason, configMetadataProvider);
1858 if (!producer) {
1859 return invalidConfigReason;
1860 }
1861 allMetricProducers.push_back(producer.value());
1862 }
1863 for (int i = 0; i < config.no_report_metric_size(); ++i) {
1864 const auto no_report_metric = config.no_report_metric(i);
1865 if (metricMap.find(no_report_metric) == metricMap.end()) {
1866 ALOGW("no_report_metric %" PRId64 " not exist", no_report_metric);
1867 return InvalidConfigReason(INVALID_CONFIG_REASON_NO_REPORT_METRIC_NOT_FOUND,
1868 no_report_metric);
1869 }
1870 noReportMetricIds.insert(no_report_metric);
1871 }
1872
1873 const set<int> whitelistedAtomIds(config.whitelisted_atom_ids().begin(),
1874 config.whitelisted_atom_ids().end());
1875 for (const auto& it : allMetricProducers) {
1876 // Register metrics to StateTrackers
1877 for (int atomId : it->getSlicedStateAtoms()) {
1878 // Register listener for non-whitelisted atoms only. Using whitelisted atom as a sliced
1879 // state atom is not allowed.
1880 if (whitelistedAtomIds.find(atomId) == whitelistedAtomIds.end()) {
1881 StateManager::getInstance().registerListener(atomId, it);
1882 } else {
1883 return InvalidConfigReason(
1884 INVALID_CONFIG_REASON_METRIC_SLICED_STATE_ATOM_ALLOWED_FROM_ANY_UID,
1885 it->getMetricId());
1886 }
1887 }
1888 }
1889 return nullopt;
1890 }
1891
initAlerts(const StatsdConfig & config,const int64_t currentTimeNs,const unordered_map<int64_t,int> & metricProducerMap,unordered_map<int64_t,int> & alertTrackerMap,const sp<AlarmMonitor> & anomalyAlarmMonitor,vector<sp<MetricProducer>> & allMetricProducers,vector<sp<AnomalyTracker>> & allAnomalyTrackers)1892 optional<InvalidConfigReason> initAlerts(const StatsdConfig& config, const int64_t currentTimeNs,
1893 const unordered_map<int64_t, int>& metricProducerMap,
1894 unordered_map<int64_t, int>& alertTrackerMap,
1895 const sp<AlarmMonitor>& anomalyAlarmMonitor,
1896 vector<sp<MetricProducer>>& allMetricProducers,
1897 vector<sp<AnomalyTracker>>& allAnomalyTrackers) {
1898 optional<InvalidConfigReason> invalidConfigReason;
1899 for (int i = 0; i < config.alert_size(); i++) {
1900 const Alert& alert = config.alert(i);
1901 alertTrackerMap.insert(std::make_pair(alert.id(), allAnomalyTrackers.size()));
1902 optional<sp<AnomalyTracker>> anomalyTracker = createAnomalyTracker(
1903 alert, anomalyAlarmMonitor, UpdateStatus::UPDATE_NEW, currentTimeNs,
1904 metricProducerMap, allMetricProducers, invalidConfigReason);
1905 if (!anomalyTracker) {
1906 return invalidConfigReason;
1907 }
1908 allAnomalyTrackers.push_back(anomalyTracker.value());
1909 }
1910 return initSubscribersForSubscriptionType(config, Subscription::ALERT, alertTrackerMap,
1911 allAnomalyTrackers);
1912 }
1913
initAlarms(const StatsdConfig & config,const ConfigKey & key,const sp<AlarmMonitor> & periodicAlarmMonitor,const int64_t timeBaseNs,const int64_t currentTimeNs,vector<sp<AlarmTracker>> & allAlarmTrackers)1914 optional<InvalidConfigReason> initAlarms(const StatsdConfig& config, const ConfigKey& key,
1915 const sp<AlarmMonitor>& periodicAlarmMonitor,
1916 const int64_t timeBaseNs, const int64_t currentTimeNs,
1917 vector<sp<AlarmTracker>>& allAlarmTrackers) {
1918 unordered_map<int64_t, int> alarmTrackerMap;
1919 int64_t startMillis = timeBaseNs / 1000 / 1000;
1920 int64_t currentTimeMillis = currentTimeNs / 1000 / 1000;
1921 for (int i = 0; i < config.alarm_size(); i++) {
1922 const Alarm& alarm = config.alarm(i);
1923 if (alarm.offset_millis() <= 0) {
1924 ALOGW("Alarm offset_millis should be larger than 0.");
1925 return createInvalidConfigReasonWithAlarm(
1926 INVALID_CONFIG_REASON_ALARM_OFFSET_LESS_THAN_OR_EQUAL_ZERO, alarm.id());
1927 }
1928 if (alarm.period_millis() <= 0) {
1929 ALOGW("Alarm period_millis should be larger than 0.");
1930 return createInvalidConfigReasonWithAlarm(
1931 INVALID_CONFIG_REASON_ALARM_PERIOD_LESS_THAN_OR_EQUAL_ZERO, alarm.id());
1932 }
1933 alarmTrackerMap.insert(std::make_pair(alarm.id(), allAlarmTrackers.size()));
1934 allAlarmTrackers.push_back(
1935 new AlarmTracker(startMillis, currentTimeMillis, alarm, key, periodicAlarmMonitor));
1936 }
1937 return initSubscribersForSubscriptionType(config, Subscription::ALARM, alarmTrackerMap,
1938 allAlarmTrackers);
1939 }
1940
initStatsdConfig(const ConfigKey & key,const StatsdConfig & config,const sp<UidMap> & uidMap,const sp<StatsPullerManager> & pullerManager,const sp<AlarmMonitor> & anomalyAlarmMonitor,const sp<AlarmMonitor> & periodicAlarmMonitor,const int64_t timeBaseNs,const int64_t currentTimeNs,const wp<ConfigMetadataProvider> configMetadataProvider,std::unordered_map<int,std::vector<int>> & allTagIdsToMatchersMap,vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,unordered_map<int64_t,int> & atomMatchingTrackerMap,vector<sp<ConditionTracker>> & allConditionTrackers,unordered_map<int64_t,int> & conditionTrackerMap,vector<sp<MetricProducer>> & allMetricProducers,unordered_map<int64_t,int> & metricProducerMap,vector<sp<AnomalyTracker>> & allAnomalyTrackers,vector<sp<AlarmTracker>> & allPeriodicAlarmTrackers,unordered_map<int,std::vector<int>> & conditionToMetricMap,unordered_map<int,std::vector<int>> & trackerToMetricMap,unordered_map<int,std::vector<int>> & trackerToConditionMap,unordered_map<int,std::vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,std::vector<int>> & deactivationAtomTrackerToMetricMap,unordered_map<int64_t,int> & alertTrackerMap,vector<int> & metricsWithActivation,map<int64_t,uint64_t> & stateProtoHashes,set<int64_t> & noReportMetricIds)1941 optional<InvalidConfigReason> initStatsdConfig(
1942 const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
1943 const sp<StatsPullerManager>& pullerManager, const sp<AlarmMonitor>& anomalyAlarmMonitor,
1944 const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
1945 const int64_t currentTimeNs, const wp<ConfigMetadataProvider> configMetadataProvider,
1946 std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
1947 vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
1948 unordered_map<int64_t, int>& atomMatchingTrackerMap,
1949 vector<sp<ConditionTracker>>& allConditionTrackers,
1950 unordered_map<int64_t, int>& conditionTrackerMap,
1951 vector<sp<MetricProducer>>& allMetricProducers,
1952 unordered_map<int64_t, int>& metricProducerMap,
1953 vector<sp<AnomalyTracker>>& allAnomalyTrackers,
1954 vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
1955 unordered_map<int, std::vector<int>>& conditionToMetricMap,
1956 unordered_map<int, std::vector<int>>& trackerToMetricMap,
1957 unordered_map<int, std::vector<int>>& trackerToConditionMap,
1958 unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
1959 unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
1960 unordered_map<int64_t, int>& alertTrackerMap, vector<int>& metricsWithActivation,
1961 map<int64_t, uint64_t>& stateProtoHashes, set<int64_t>& noReportMetricIds) {
1962 vector<ConditionState> initialConditionCache;
1963 unordered_map<int64_t, int> stateAtomIdMap;
1964 unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
1965
1966 if (config.package_certificate_hash_size_bytes() > UINT8_MAX) {
1967 ALOGE("Invalid value for package_certificate_hash_size_bytes: %d",
1968 config.package_certificate_hash_size_bytes());
1969 return InvalidConfigReason(INVALID_CONFIG_REASON_PACKAGE_CERT_HASH_SIZE_TOO_LARGE);
1970 }
1971
1972 optional<InvalidConfigReason> invalidConfigReason =
1973 initAtomMatchingTrackers(config, uidMap, atomMatchingTrackerMap,
1974 allAtomMatchingTrackers, allTagIdsToMatchersMap);
1975 if (invalidConfigReason.has_value()) {
1976 ALOGE("initAtomMatchingTrackers failed");
1977 return invalidConfigReason;
1978 }
1979 VLOG("initAtomMatchingTrackers succeed...");
1980
1981 invalidConfigReason =
1982 initConditions(key, config, atomMatchingTrackerMap, conditionTrackerMap,
1983 allConditionTrackers, trackerToConditionMap, initialConditionCache);
1984 if (invalidConfigReason.has_value()) {
1985 ALOGE("initConditionTrackers failed");
1986 return invalidConfigReason;
1987 }
1988
1989 invalidConfigReason = initStates(config, stateAtomIdMap, allStateGroupMaps, stateProtoHashes);
1990 if (invalidConfigReason.has_value()) {
1991 ALOGE("initStates failed");
1992 return invalidConfigReason;
1993 }
1994
1995 invalidConfigReason = initMetrics(
1996 key, config, timeBaseNs, currentTimeNs, pullerManager, atomMatchingTrackerMap,
1997 conditionTrackerMap, allAtomMatchingTrackers, stateAtomIdMap, allStateGroupMaps,
1998 allConditionTrackers, initialConditionCache, allMetricProducers, conditionToMetricMap,
1999 trackerToMetricMap, metricProducerMap, noReportMetricIds,
2000 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
2001 metricsWithActivation, configMetadataProvider);
2002 if (invalidConfigReason.has_value()) {
2003 ALOGE("initMetricProducers failed");
2004 return invalidConfigReason;
2005 }
2006
2007 invalidConfigReason = initAlerts(config, currentTimeNs, metricProducerMap, alertTrackerMap,
2008 anomalyAlarmMonitor, allMetricProducers, allAnomalyTrackers);
2009 if (invalidConfigReason.has_value()) {
2010 ALOGE("initAlerts failed");
2011 return invalidConfigReason;
2012 }
2013
2014 invalidConfigReason = initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
2015 allPeriodicAlarmTrackers);
2016 if (invalidConfigReason.has_value()) {
2017 ALOGE("initAlarms failed");
2018 return invalidConfigReason;
2019 }
2020
2021 return nullopt;
2022 }
2023
2024 } // namespace statsd
2025 } // namespace os
2026 } // namespace android
2027