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