• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 std::unordered_map<int64_t,int> & stateAtomIdMap,const std::unordered_map<int64_t,std::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)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 std::unordered_map<int64_t, int>& stateAtomIdMap,
842         const std::unordered_map<int64_t, std::unordered_map<int, int64_t>>& allStateGroupMaps,
843         const unordered_map<int64_t, int>& metricToActivationMap,
844         unordered_map<int, vector<int>>& trackerToMetricMap,
845         unordered_map<int, vector<int>>& conditionToMetricMap,
846         unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
847         unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
848         vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason,
849         const wp<ConfigMetadataProvider> configMetadataProvider) {
850     if (!metric.has_id() || !metric.has_what()) {
851         ALOGE("cannot find the metric name or what in config");
852         invalidConfigReason =
853                 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
854         return nullopt;
855     }
856 
857     if (metric.has_fields_filter()) {
858         const FieldFilter& filter = metric.fields_filter();
859         if ((filter.has_fields() && !hasLeafNode(filter.fields())) ||
860             (filter.has_omit_fields() && !hasLeafNode(filter.omit_fields()))) {
861             ALOGW("Incorrect field filter setting in EventMetric %lld", (long long)metric.id());
862             invalidConfigReason = InvalidConfigReason(
863                     INVALID_CONFIG_REASON_METRIC_INCORRECT_FIELD_FILTER, metric.id());
864             return nullopt;
865         }
866     }
867 
868     int trackerIndex;
869     invalidConfigReason = handleMetricWithAtomMatchingTrackers(
870             metric.what(), metric.id(), metricIndex, false, allAtomMatchingTrackers,
871             atomMatchingTrackerMap, trackerToMetricMap, trackerIndex);
872     if (invalidConfigReason.has_value()) {
873         return nullopt;
874     }
875 
876     int conditionIndex = -1;
877     if (metric.has_condition()) {
878         invalidConfigReason = handleMetricWithConditions(
879                 metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
880                 allConditionTrackers, conditionIndex, conditionToMetricMap);
881         if (invalidConfigReason.has_value()) {
882             return nullopt;
883         }
884     } else {
885         if (metric.links_size() > 0) {
886             ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
887             invalidConfigReason = InvalidConfigReason(
888                     INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
889             return nullopt;
890         }
891     }
892 
893     std::vector<int> slicedStateAtoms;
894     unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
895     if (metric.slice_by_state_size() > 0) {
896         invalidConfigReason =
897                 handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
898                                        allStateGroupMaps, slicedStateAtoms, stateGroupMap);
899         if (invalidConfigReason.has_value()) {
900             return nullopt;
901         }
902     } else if (metric.state_link_size() > 0) {
903         ALOGW("EventMetric has a MetricStateLink but doesn't have a sliced state");
904         invalidConfigReason =
905                 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
906         return nullopt;
907     }
908 
909     if (metric.sampling_percentage() < 1 || metric.sampling_percentage() > 100) {
910         invalidConfigReason = InvalidConfigReason(
911                 INVALID_CONFIG_REASON_METRIC_INCORRECT_SAMPLING_PERCENTAGE, metric.id());
912         return nullopt;
913     }
914 
915     unordered_map<int, shared_ptr<Activation>> eventActivationMap;
916     unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
917     invalidConfigReason = handleMetricActivation(
918             config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
919             activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
920             metricsWithActivation, eventActivationMap, eventDeactivationMap);
921     if (invalidConfigReason.has_value()) return nullptr;
922 
923     uint64_t metricHash;
924     invalidConfigReason =
925             getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
926     if (invalidConfigReason.has_value()) {
927         return nullopt;
928     }
929 
930     sp<MetricProducer> metricProducer;
931     if (config.has_restricted_metrics_delegate_package_name()) {
932         metricProducer = new RestrictedEventMetricProducer(
933                 key, metric, conditionIndex, initialConditionCache, wizard, metricHash, timeBaseNs,
934                 configMetadataProvider, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
935                 stateGroupMap);
936     } else {
937         metricProducer = new EventMetricProducer(
938                 key, metric, conditionIndex, initialConditionCache, wizard, metricHash, timeBaseNs,
939                 configMetadataProvider, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
940                 stateGroupMap);
941     }
942 
943     invalidConfigReason = setUidFieldsIfNecessary(metric, metricProducer);
944     if (invalidConfigReason.has_value()) {
945         return nullopt;
946     }
947 
948     return metricProducer;
949 }
950 
951 namespace {  // anonymous namespace
hasClientAggregatedBins(const ValueMetric & metric,int binConfigIndex)952 bool hasClientAggregatedBins(const ValueMetric& metric, int binConfigIndex) {
953     return metric.histogram_bin_configs_size() > binConfigIndex &&
954            metric.histogram_bin_configs(binConfigIndex).has_client_aggregated_bins();
955 }
956 
validatePositionAllInValueFields(const ValueMetric & metric,int binConfigIndex,ValueMetric::AggregationType aggType,vector<Matcher>::iterator matchersStartIt,const vector<Matcher>::iterator & matchersEndIt)957 optional<InvalidConfigReason> validatePositionAllInValueFields(
958         const ValueMetric& metric, int binConfigIndex, ValueMetric::AggregationType aggType,
959         vector<Matcher>::iterator matchersStartIt, const vector<Matcher>::iterator& matchersEndIt) {
960     if (aggType == ValueMetric::HISTOGRAM && hasClientAggregatedBins(metric, binConfigIndex)) {
961         while (matchersStartIt != matchersEndIt) {
962             if (!matchersStartIt->hasAllPositionMatcher()) {
963                 ALOGE("value_field requires position ALL for client-aggregated histograms. "
964                       "ValueMetric \"%lld\"",
965                       (long long)metric.id());
966                 return InvalidConfigReason(
967                         INVALID_CONFIG_REASON_VALUE_METRIC_HIST_CLIENT_AGGREGATED_NO_POSITION_ALL,
968                         metric.id());
969             }
970             matchersStartIt++;
971         }
972         return nullopt;
973     }
974     while (matchersStartIt != matchersEndIt) {
975         if (matchersStartIt->hasAllPositionMatcher()) {
976             ALOGE("value_field with position ALL is only supported for client-aggregated "
977                   "histograms. ValueMetric \"%lld\"",
978                   (long long)metric.id());
979             return InvalidConfigReason(
980                     INVALID_CONFIG_REASON_VALUE_METRIC_VALUE_FIELD_HAS_POSITION_ALL, metric.id());
981         }
982         matchersStartIt++;
983     }
984     return nullopt;
985 }
986 }  // anonymous namespace
987 
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)988 optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata(
989         const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
990         const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
991         const ValueMetric& metric, const int metricIndex,
992         const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
993         const unordered_map<int64_t, int>& atomMatchingTrackerMap,
994         vector<sp<ConditionTracker>>& allConditionTrackers,
995         const unordered_map<int64_t, int>& conditionTrackerMap,
996         const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
997         const sp<EventMatcherWizard>& matcherWizard,
998         const unordered_map<int64_t, int>& stateAtomIdMap,
999         const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
1000         const unordered_map<int64_t, int>& metricToActivationMap,
1001         unordered_map<int, vector<int>>& trackerToMetricMap,
1002         unordered_map<int, vector<int>>& conditionToMetricMap,
1003         unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
1004         unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
1005         vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason,
1006         const wp<ConfigMetadataProvider> configMetadataProvider) {
1007     if (!metric.has_id() || !metric.has_what()) {
1008         ALOGE("cannot find metric id or \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
1009         invalidConfigReason =
1010                 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
1011         return nullopt;
1012     }
1013     if (!metric.has_value_field()) {
1014         ALOGE("cannot find \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
1015         invalidConfigReason = InvalidConfigReason(
1016                 INVALID_CONFIG_REASON_VALUE_METRIC_MISSING_VALUE_FIELD, metric.id());
1017         return nullopt;
1018     }
1019     std::vector<Matcher> fieldMatchers;
1020     translateFieldMatcher(metric.value_field(), &fieldMatchers);
1021     if (fieldMatchers.size() < 1) {
1022         ALOGE("incorrect \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
1023         invalidConfigReason = InvalidConfigReason(
1024                 INVALID_CONFIG_REASON_VALUE_METRIC_HAS_INCORRECT_VALUE_FIELD, metric.id());
1025         return nullopt;
1026     }
1027 
1028     std::vector<ValueMetric::AggregationType> aggregationTypes;
1029     int histogramCount = 0;
1030     if (!metric.aggregation_types().empty()) {
1031         if (metric.has_aggregation_type()) {
1032             invalidConfigReason = InvalidConfigReason(
1033                     INVALID_CONFIG_REASON_VALUE_METRIC_DEFINES_SINGLE_AND_MULTIPLE_AGG_TYPES,
1034                     metric.id());
1035             return nullopt;
1036         }
1037         if (metric.aggregation_types_size() != (int)fieldMatchers.size()) {
1038             invalidConfigReason = InvalidConfigReason(
1039                     INVALID_CONFIG_REASON_VALUE_METRIC_AGG_TYPES_DNE_VALUE_FIELDS_SIZE,
1040                     metric.id());
1041             return nullopt;
1042         }
1043         for (int i = 0; i < metric.aggregation_types_size(); i++) {
1044             const ValueMetric::AggregationType aggType = metric.aggregation_types(i);
1045             aggregationTypes.push_back(aggType);
1046             if (aggType == ValueMetric::HISTOGRAM) {
1047                 histogramCount++;
1048             }
1049             invalidConfigReason = validatePositionAllInValueFields(
1050                     metric, histogramCount - 1, aggType, fieldMatchers.begin() + i,
1051                     fieldMatchers.begin() + i + 1);
1052             if (invalidConfigReason != nullopt) {
1053                 return nullopt;
1054             }
1055         }
1056     } else {  // aggregation_type() is set or default is used.
1057         const ValueMetric::AggregationType aggType = metric.aggregation_type();
1058         aggregationTypes.push_back(aggType);
1059         if (aggType == ValueMetric::HISTOGRAM) {
1060             histogramCount = 1;
1061         }
1062         invalidConfigReason = validatePositionAllInValueFields(
1063                 metric, 0, aggType, fieldMatchers.begin(), fieldMatchers.end());
1064         if (invalidConfigReason != nullopt) {
1065             return nullopt;
1066         }
1067     }
1068 
1069     if (metric.histogram_bin_configs_size() != histogramCount) {
1070         ALOGE("%d histogram aggregations specified but there are %d histogram_bin_configs",
1071               histogramCount, metric.histogram_bin_configs_size());
1072         invalidConfigReason = InvalidConfigReason(
1073                 INVALID_CONFIG_REASON_VALUE_METRIC_HIST_COUNT_DNE_HIST_BIN_CONFIGS_COUNT,
1074                 metric.id());
1075         return nullopt;
1076     }
1077 
1078     if (aggregationTypes.front() == ValueMetric::HISTOGRAM && metric.has_threshold()) {
1079         invalidConfigReason = InvalidConfigReason(
1080                 INVALID_CONFIG_REASON_VALUE_METRIC_HIST_WITH_UPLOAD_THRESHOLD, metric.id());
1081         return nullopt;
1082     }
1083 
1084     if (histogramCount > 0 && metric.has_value_direction() &&
1085         metric.value_direction() != ValueMetric::INCREASING) {
1086         invalidConfigReason = InvalidConfigReason(
1087                 INVALID_CONFIG_REASON_VALUE_METRIC_HIST_INVALID_VALUE_DIRECTION, metric.id());
1088         return nullopt;
1089     }
1090 
1091     ParseHistogramBinConfigsResult parseBinConfigsResult =
1092             parseHistogramBinConfigs(metric, aggregationTypes);
1093     if (std::holds_alternative<InvalidConfigReason>(parseBinConfigsResult)) {
1094         invalidConfigReason = std::get<InvalidConfigReason>(parseBinConfigsResult);
1095         return nullopt;
1096     }
1097 
1098     int trackerIndex;
1099     invalidConfigReason = handleMetricWithAtomMatchingTrackers(
1100             metric.what(), metric.id(), metricIndex,
1101             /*enforceOneAtom=*/true, allAtomMatchingTrackers, atomMatchingTrackerMap,
1102             trackerToMetricMap, trackerIndex);
1103     if (invalidConfigReason.has_value()) {
1104         return nullopt;
1105     }
1106 
1107     const sp<AtomMatchingTracker>& atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
1108     int atomTagId = *(atomMatcher->getAtomIds().begin());
1109     int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1;
1110 
1111     int conditionIndex = -1;
1112     if (metric.has_condition()) {
1113         invalidConfigReason = handleMetricWithConditions(
1114                 metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
1115                 allConditionTrackers, conditionIndex, conditionToMetricMap);
1116         if (invalidConfigReason.has_value()) {
1117             return nullopt;
1118         }
1119     } else if (metric.links_size() > 0) {
1120         ALOGE("metrics has a MetricConditionLink but doesn't have a condition");
1121         invalidConfigReason = InvalidConfigReason(
1122                 INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
1123         return nullopt;
1124     }
1125 
1126     std::vector<int> slicedStateAtoms;
1127     unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
1128     if (metric.slice_by_state_size() > 0) {
1129         invalidConfigReason =
1130                 handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
1131                                        allStateGroupMaps, slicedStateAtoms, stateGroupMap);
1132         if (invalidConfigReason.has_value()) {
1133             return nullopt;
1134         }
1135     } else if (metric.state_link_size() > 0) {
1136         ALOGE("ValueMetric has a MetricStateLink but doesn't have a sliced state");
1137         invalidConfigReason =
1138                 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
1139         return nullopt;
1140     }
1141 
1142     // Check that all metric state links are a subset of dimensions_in_what fields.
1143     std::vector<Matcher> dimensionsInWhat;
1144     translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
1145     for (const auto& stateLink : metric.state_link()) {
1146         invalidConfigReason = handleMetricWithStateLink(metric.id(), stateLink.fields_in_what(),
1147                                                         dimensionsInWhat);
1148         if (invalidConfigReason.has_value()) {
1149             ALOGW("ValueMetric's MetricStateLinks must be a subset of the dimensions in what");
1150             return nullopt;
1151         }
1152     }
1153 
1154     unordered_map<int, shared_ptr<Activation>> eventActivationMap;
1155     unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
1156     invalidConfigReason = handleMetricActivation(
1157             config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
1158             activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1159             metricsWithActivation, eventActivationMap, eventDeactivationMap);
1160     if (invalidConfigReason.has_value()) {
1161         return nullopt;
1162     }
1163 
1164     uint64_t metricHash;
1165     invalidConfigReason =
1166             getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
1167     if (invalidConfigReason.has_value()) {
1168         return nullopt;
1169     }
1170 
1171     const TimeUnit bucketSizeTimeUnit =
1172             metric.bucket() == TIME_UNIT_UNSPECIFIED ? ONE_HOUR : metric.bucket();
1173     const int64_t bucketSizeNs =
1174             MillisToNano(TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), bucketSizeTimeUnit));
1175 
1176     const bool containsAnyPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what());
1177     const bool shouldUseNestedDimensions = ShouldUseNestedDimensions(metric.dimensions_in_what());
1178 
1179     const auto [dimensionSoftLimit, dimensionHardLimit] =
1180             StatsdStats::getAtomDimensionKeySizeLimits(
1181                     pullTagId,
1182                     StatsdStats::clampDimensionKeySizeLimit(metric.max_dimensions_per_bucket()));
1183 
1184     // get the condition_correction_threshold_nanos value
1185     const optional<int64_t> conditionCorrectionThresholdNs =
1186             metric.has_condition_correction_threshold_nanos()
1187                     ? optional<int64_t>(metric.condition_correction_threshold_nanos())
1188                     : nullopt;
1189 
1190     const vector<optional<const BinStarts>>& binStartsList =
1191             std::get<vector<optional<const BinStarts>>>(parseBinConfigsResult);
1192     sp<MetricProducer> metricProducer = new NumericValueMetricProducer(
1193             key, metric, metricHash, {pullTagId, pullerManager},
1194             {timeBaseNs, currentTimeNs, bucketSizeNs, metric.min_bucket_size_nanos(),
1195              conditionCorrectionThresholdNs, getAppUpgradeBucketSplit(metric)},
1196             {containsAnyPositionInDimensionsInWhat, shouldUseNestedDimensions, trackerIndex,
1197              matcherWizard, metric.dimensions_in_what(), fieldMatchers, aggregationTypes,
1198              binStartsList},
1199             {conditionIndex, metric.links(), initialConditionCache, wizard},
1200             {metric.state_link(), slicedStateAtoms, stateGroupMap},
1201             {eventActivationMap, eventDeactivationMap}, {dimensionSoftLimit, dimensionHardLimit},
1202             configMetadataProvider);
1203 
1204     SamplingInfo samplingInfo;
1205     if (metric.has_dimensional_sampling_info()) {
1206         invalidConfigReason = handleMetricWithDimensionalSampling(
1207                 metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
1208         if (invalidConfigReason.has_value()) {
1209             return nullopt;
1210         }
1211         metricProducer->setSamplingInfo(samplingInfo);
1212     }
1213 
1214     invalidConfigReason = setUidFieldsIfNecessary(metric, metricProducer);
1215     if (invalidConfigReason.has_value()) {
1216         return nullopt;
1217     }
1218 
1219     return metricProducer;
1220 }
1221 
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)1222 optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata(
1223         const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
1224         const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
1225         const KllMetric& metric, const int metricIndex,
1226         const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
1227         const unordered_map<int64_t, int>& atomMatchingTrackerMap,
1228         vector<sp<ConditionTracker>>& allConditionTrackers,
1229         const unordered_map<int64_t, int>& conditionTrackerMap,
1230         const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
1231         const sp<EventMatcherWizard>& matcherWizard,
1232         const unordered_map<int64_t, int>& stateAtomIdMap,
1233         const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
1234         const unordered_map<int64_t, int>& metricToActivationMap,
1235         unordered_map<int, vector<int>>& trackerToMetricMap,
1236         unordered_map<int, vector<int>>& conditionToMetricMap,
1237         unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
1238         unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
1239         vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason,
1240         const wp<ConfigMetadataProvider> configMetadataProvider) {
1241     if (!metric.has_id() || !metric.has_what()) {
1242         ALOGE("cannot find metric id or \"what\" in KllMetric \"%lld\"", (long long)metric.id());
1243         invalidConfigReason =
1244                 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
1245         return nullopt;
1246     }
1247     if (!metric.has_kll_field()) {
1248         ALOGE("cannot find \"kll_field\" in KllMetric \"%lld\"", (long long)metric.id());
1249         invalidConfigReason = InvalidConfigReason(
1250                 INVALID_CONFIG_REASON_KLL_METRIC_MISSING_KLL_FIELD, metric.id());
1251         return nullopt;
1252     }
1253     if (HasPositionALL(metric.kll_field())) {
1254         ALOGE("kll field with position ALL is not supported. KllMetric \"%lld\"",
1255               (long long)metric.id());
1256         invalidConfigReason = InvalidConfigReason(
1257                 INVALID_CONFIG_REASON_KLL_METRIC_KLL_FIELD_HAS_POSITION_ALL, metric.id());
1258         return nullopt;
1259     }
1260     std::vector<Matcher> fieldMatchers;
1261     translateFieldMatcher(metric.kll_field(), &fieldMatchers);
1262     if (fieldMatchers.empty()) {
1263         ALOGE("incorrect \"kll_field\" in KllMetric \"%lld\"", (long long)metric.id());
1264         invalidConfigReason = InvalidConfigReason(
1265                 INVALID_CONFIG_REASON_KLL_METRIC_HAS_INCORRECT_KLL_FIELD, metric.id());
1266         return nullopt;
1267     }
1268 
1269     int trackerIndex;
1270     invalidConfigReason = handleMetricWithAtomMatchingTrackers(
1271             metric.what(), metric.id(), metricIndex,
1272             /*enforceOneAtom=*/true, allAtomMatchingTrackers, atomMatchingTrackerMap,
1273             trackerToMetricMap, trackerIndex);
1274     if (invalidConfigReason.has_value()) {
1275         return nullopt;
1276     }
1277 
1278     int conditionIndex = -1;
1279     if (metric.has_condition()) {
1280         invalidConfigReason = handleMetricWithConditions(
1281                 metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
1282                 allConditionTrackers, conditionIndex, conditionToMetricMap);
1283         if (invalidConfigReason.has_value()) {
1284             return nullopt;
1285         }
1286     } else if (metric.links_size() > 0) {
1287         ALOGE("metrics has a MetricConditionLink but doesn't have a condition");
1288         invalidConfigReason = InvalidConfigReason(
1289                 INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
1290         return nullopt;
1291     }
1292 
1293     std::vector<int> slicedStateAtoms;
1294     unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
1295     if (metric.slice_by_state_size() > 0) {
1296         invalidConfigReason =
1297                 handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
1298                                        allStateGroupMaps, slicedStateAtoms, stateGroupMap);
1299         if (invalidConfigReason.has_value()) {
1300             return nullopt;
1301         }
1302     } else if (metric.state_link_size() > 0) {
1303         ALOGE("KllMetric has a MetricStateLink but doesn't have a sliced state");
1304         invalidConfigReason =
1305                 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
1306         return nullopt;
1307     }
1308 
1309     // Check that all metric state links are a subset of dimensions_in_what fields.
1310     std::vector<Matcher> dimensionsInWhat;
1311     translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
1312     for (const auto& stateLink : metric.state_link()) {
1313         invalidConfigReason = handleMetricWithStateLink(metric.id(), stateLink.fields_in_what(),
1314                                                         dimensionsInWhat);
1315         if (invalidConfigReason.has_value()) {
1316             ALOGW("KllMetric's MetricStateLinks must be a subset of the dimensions in what");
1317             return nullopt;
1318         }
1319     }
1320 
1321     unordered_map<int, shared_ptr<Activation>> eventActivationMap;
1322     unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
1323     invalidConfigReason = handleMetricActivation(
1324             config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
1325             activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1326             metricsWithActivation, eventActivationMap, eventDeactivationMap);
1327     if (invalidConfigReason.has_value()) {
1328         return nullopt;
1329     }
1330 
1331     uint64_t metricHash;
1332     invalidConfigReason =
1333             getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
1334     if (invalidConfigReason.has_value()) {
1335         return nullopt;
1336     }
1337 
1338     const TimeUnit bucketSizeTimeUnit =
1339             metric.bucket() == TIME_UNIT_UNSPECIFIED ? ONE_HOUR : metric.bucket();
1340     const int64_t bucketSizeNs =
1341             MillisToNano(TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), bucketSizeTimeUnit));
1342 
1343     const bool containsAnyPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what());
1344     const bool shouldUseNestedDimensions = ShouldUseNestedDimensions(metric.dimensions_in_what());
1345 
1346     const sp<AtomMatchingTracker>& atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
1347     const int atomTagId = *(atomMatcher->getAtomIds().begin());
1348     const auto [dimensionSoftLimit, dimensionHardLimit] =
1349             StatsdStats::getAtomDimensionKeySizeLimits(
1350                     atomTagId,
1351                     StatsdStats::clampDimensionKeySizeLimit(metric.max_dimensions_per_bucket()));
1352 
1353     sp<MetricProducer> metricProducer = new KllMetricProducer(
1354             key, metric, metricHash, {/*pullTagId=*/-1, pullerManager},
1355             {timeBaseNs, currentTimeNs, bucketSizeNs, metric.min_bucket_size_nanos(),
1356              /*conditionCorrectionThresholdNs=*/nullopt, getAppUpgradeBucketSplit(metric)},
1357             {containsAnyPositionInDimensionsInWhat,
1358              shouldUseNestedDimensions,
1359              trackerIndex,
1360              matcherWizard,
1361              metric.dimensions_in_what(),
1362              fieldMatchers,
1363              {}},
1364             {conditionIndex, metric.links(), initialConditionCache, wizard},
1365             {metric.state_link(), slicedStateAtoms, stateGroupMap},
1366             {eventActivationMap, eventDeactivationMap}, {dimensionSoftLimit, dimensionHardLimit},
1367             configMetadataProvider);
1368 
1369     SamplingInfo samplingInfo;
1370     if (metric.has_dimensional_sampling_info()) {
1371         invalidConfigReason = handleMetricWithDimensionalSampling(
1372                 metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
1373         if (invalidConfigReason.has_value()) {
1374             return nullopt;
1375         }
1376         metricProducer->setSamplingInfo(samplingInfo);
1377     }
1378 
1379     invalidConfigReason = setUidFieldsIfNecessary(metric, metricProducer);
1380     if (invalidConfigReason.has_value()) {
1381         return nullopt;
1382     }
1383 
1384     return metricProducer;
1385 }
1386 
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 std::unordered_map<int64_t,int> & stateAtomIdMap,const std::unordered_map<int64_t,std::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)1387 optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
1388         const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
1389         const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
1390         const GaugeMetric& metric, const int metricIndex,
1391         const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
1392         const unordered_map<int64_t, int>& atomMatchingTrackerMap,
1393         vector<sp<ConditionTracker>>& allConditionTrackers,
1394         const unordered_map<int64_t, int>& conditionTrackerMap,
1395         const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
1396         const sp<EventMatcherWizard>& matcherWizard,
1397         const std::unordered_map<int64_t, int>& stateAtomIdMap,
1398         const std::unordered_map<int64_t, std::unordered_map<int, int64_t>>& allStateGroupMaps,
1399         const unordered_map<int64_t, int>& metricToActivationMap,
1400         unordered_map<int, vector<int>>& trackerToMetricMap,
1401         unordered_map<int, vector<int>>& conditionToMetricMap,
1402         unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
1403         unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
1404         vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason,
1405         const wp<ConfigMetadataProvider> configMetadataProvider) {
1406     if (!metric.has_id() || !metric.has_what()) {
1407         ALOGE("cannot find metric id or \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
1408         invalidConfigReason =
1409                 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
1410         return nullopt;
1411     }
1412 
1413     if (metric.has_gauge_fields_filter()) {
1414         const FieldFilter& filter = metric.gauge_fields_filter();
1415         if ((filter.has_fields() && !hasLeafNode(filter.fields())) ||
1416             (filter.has_omit_fields() && !hasLeafNode(filter.omit_fields()))) {
1417             ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
1418             invalidConfigReason = InvalidConfigReason(
1419                     INVALID_CONFIG_REASON_METRIC_INCORRECT_FIELD_FILTER, metric.id());
1420             return nullopt;
1421         }
1422     }
1423 
1424     int trackerIndex;
1425     invalidConfigReason = handleMetricWithAtomMatchingTrackers(
1426             metric.what(), metric.id(), metricIndex, true, allAtomMatchingTrackers,
1427             atomMatchingTrackerMap, trackerToMetricMap, trackerIndex);
1428     if (invalidConfigReason.has_value()) {
1429         return nullopt;
1430     }
1431 
1432     const sp<AtomMatchingTracker>& atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
1433     int atomTagId = *(atomMatcher->getAtomIds().begin());
1434     int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1;
1435 
1436     int triggerTrackerIndex;
1437     int triggerAtomId = -1;
1438     if (metric.has_trigger_event()) {
1439         if (pullTagId == -1) {
1440             ALOGW("Pull atom not specified for trigger");
1441             invalidConfigReason = InvalidConfigReason(
1442                     INVALID_CONFIG_REASON_GAUGE_METRIC_TRIGGER_NO_PULL_ATOM, metric.id());
1443             return nullopt;
1444         }
1445         // trigger_event should be used with FIRST_N_SAMPLES
1446         if (metric.sampling_type() != GaugeMetric::FIRST_N_SAMPLES) {
1447             ALOGW("Gauge Metric with trigger event must have sampling type FIRST_N_SAMPLES");
1448             invalidConfigReason = InvalidConfigReason(
1449                     INVALID_CONFIG_REASON_GAUGE_METRIC_TRIGGER_NO_FIRST_N_SAMPLES, metric.id());
1450             return nullopt;
1451         }
1452         invalidConfigReason = handleMetricWithAtomMatchingTrackers(
1453                 metric.trigger_event(), metric.id(), metricIndex,
1454                 /*enforceOneAtom=*/true, allAtomMatchingTrackers, atomMatchingTrackerMap,
1455                 trackerToMetricMap, triggerTrackerIndex);
1456         if (invalidConfigReason.has_value()) {
1457             return nullopt;
1458         }
1459         const sp<AtomMatchingTracker>& triggerAtomMatcher =
1460                 allAtomMatchingTrackers.at(triggerTrackerIndex);
1461         triggerAtomId = *(triggerAtomMatcher->getAtomIds().begin());
1462     }
1463 
1464     int conditionIndex = -1;
1465     if (metric.has_condition()) {
1466         invalidConfigReason = handleMetricWithConditions(
1467                 metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
1468                 allConditionTrackers, conditionIndex, conditionToMetricMap);
1469         if (invalidConfigReason.has_value()) {
1470             return nullopt;
1471         }
1472     } else {
1473         if (metric.links_size() > 0) {
1474             ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
1475             invalidConfigReason = InvalidConfigReason(
1476                     INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
1477             return nullopt;
1478         }
1479     }
1480 
1481     std::vector<int> slicedStateAtoms;
1482     std::unordered_map<int, std::unordered_map<int, int64_t>> stateGroupMap;
1483     if (metric.slice_by_state_size() > 0) {
1484         invalidConfigReason =
1485                 handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
1486                                        allStateGroupMaps, slicedStateAtoms, stateGroupMap);
1487         if (invalidConfigReason.has_value()) {
1488             return nullopt;
1489         }
1490     } else if (metric.state_link_size() > 0) {
1491         ALOGE("GaugeMetric has a MetricStateLink but doesn't have a sliced state");
1492         invalidConfigReason =
1493                 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
1494         return nullopt;
1495     }
1496 
1497     if (pullTagId != -1 && metric.sampling_percentage() != 100) {
1498         invalidConfigReason = InvalidConfigReason(
1499                 INVALID_CONFIG_REASON_GAUGE_METRIC_PULLED_WITH_SAMPLING, metric.id());
1500         return nullopt;
1501     }
1502 
1503     if (metric.sampling_percentage() < 1 || metric.sampling_percentage() > 100) {
1504         invalidConfigReason = InvalidConfigReason(
1505                 INVALID_CONFIG_REASON_METRIC_INCORRECT_SAMPLING_PERCENTAGE, metric.id());
1506         return nullopt;
1507     }
1508 
1509     if (metric.pull_probability() < 1 || metric.pull_probability() > 100) {
1510         invalidConfigReason = InvalidConfigReason(
1511                 INVALID_CONFIG_REASON_METRIC_INCORRECT_PULL_PROBABILITY, metric.id());
1512         return nullopt;
1513     }
1514 
1515     if (metric.pull_probability() != 100) {
1516         if (pullTagId == -1) {
1517             invalidConfigReason = InvalidConfigReason(
1518                     INVALID_CONFIG_REASON_GAUGE_METRIC_PUSHED_WITH_PULL_PROBABILITY, metric.id());
1519             return nullopt;
1520         }
1521         if (metric.sampling_type() == GaugeMetric::RANDOM_ONE_SAMPLE) {
1522             invalidConfigReason = InvalidConfigReason(
1523                     INVALID_CONFIG_REASON_GAUGE_METRIC_RANDOM_ONE_SAMPLE_WITH_PULL_PROBABILITY,
1524                     metric.id());
1525             return nullopt;
1526         }
1527     }
1528 
1529     unordered_map<int, shared_ptr<Activation>> eventActivationMap;
1530     unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
1531     invalidConfigReason = handleMetricActivation(
1532             config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
1533             activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1534             metricsWithActivation, eventActivationMap, eventDeactivationMap);
1535     if (invalidConfigReason.has_value()) {
1536         return nullopt;
1537     }
1538 
1539     uint64_t metricHash;
1540     invalidConfigReason =
1541             getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
1542     if (invalidConfigReason.has_value()) {
1543         return nullopt;
1544     }
1545 
1546     const auto [dimensionSoftLimit, dimensionHardLimit] =
1547             StatsdStats::getAtomDimensionKeySizeLimits(
1548                     pullTagId,
1549                     StatsdStats::clampDimensionKeySizeLimit(metric.max_dimensions_per_bucket()));
1550 
1551     sp<MetricProducer> metricProducer = new GaugeMetricProducer(
1552             key, metric, conditionIndex, initialConditionCache, wizard, metricHash, trackerIndex,
1553             matcherWizard, pullTagId, triggerAtomId, atomTagId, timeBaseNs, currentTimeNs,
1554             pullerManager, configMetadataProvider, eventActivationMap, eventDeactivationMap,
1555             slicedStateAtoms, stateGroupMap, dimensionSoftLimit, dimensionHardLimit);
1556 
1557     SamplingInfo samplingInfo;
1558     std::vector<Matcher> dimensionsInWhat;
1559     translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
1560     if (metric.has_dimensional_sampling_info()) {
1561         invalidConfigReason = handleMetricWithDimensionalSampling(
1562                 metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
1563         if (invalidConfigReason.has_value()) {
1564             return nullopt;
1565         }
1566         metricProducer->setSamplingInfo(samplingInfo);
1567     }
1568 
1569     invalidConfigReason = setUidFieldsIfNecessary(metric, metricProducer);
1570     if (invalidConfigReason.has_value()) {
1571         return nullopt;
1572     }
1573 
1574     return metricProducer;
1575 }
1576 
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)1577 optional<sp<AnomalyTracker>> createAnomalyTracker(
1578         const Alert& alert, const sp<AlarmMonitor>& anomalyAlarmMonitor,
1579         const UpdateStatus& updateStatus, const int64_t currentTimeNs,
1580         const unordered_map<int64_t, int>& metricProducerMap,
1581         vector<sp<MetricProducer>>& allMetricProducers,
1582         optional<InvalidConfigReason>& invalidConfigReason) {
1583     const auto& itr = metricProducerMap.find(alert.metric_id());
1584     if (itr == metricProducerMap.end()) {
1585         ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
1586               (long long)alert.metric_id());
1587         invalidConfigReason = createInvalidConfigReasonWithAlert(
1588                 INVALID_CONFIG_REASON_ALERT_METRIC_NOT_FOUND, alert.metric_id(), alert.id());
1589         return nullopt;
1590     }
1591     if (!alert.has_trigger_if_sum_gt()) {
1592         ALOGW("invalid alert: missing threshold");
1593         invalidConfigReason = createInvalidConfigReasonWithAlert(
1594                 INVALID_CONFIG_REASON_ALERT_THRESHOLD_MISSING, alert.id());
1595         return nullopt;
1596     }
1597     if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
1598         ALOGW("invalid alert: threshold=%f num_buckets= %d", alert.trigger_if_sum_gt(),
1599               alert.num_buckets());
1600         invalidConfigReason = createInvalidConfigReasonWithAlert(
1601                 INVALID_CONFIG_REASON_ALERT_INVALID_TRIGGER_OR_NUM_BUCKETS, alert.id());
1602         return nullopt;
1603     }
1604     const int metricIndex = itr->second;
1605     sp<MetricProducer> metric = allMetricProducers[metricIndex];
1606     sp<AnomalyTracker> anomalyTracker =
1607             metric->addAnomalyTracker(alert, anomalyAlarmMonitor, updateStatus, currentTimeNs);
1608     if (anomalyTracker == nullptr) {
1609         // The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
1610         invalidConfigReason = createInvalidConfigReasonWithAlert(
1611                 INVALID_CONFIG_REASON_ALERT_CANNOT_ADD_ANOMALY, alert.metric_id(), alert.id());
1612         return nullopt;
1613     }
1614     return {anomalyTracker};
1615 }
1616 
initAtomMatchingTrackers(const StatsdConfig & config,const sp<UidMap> & uidMap,unordered_map<int64_t,int> & atomMatchingTrackerMap,vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,unordered_map<int,vector<int>> & allTagIdsToMatchersMap)1617 optional<InvalidConfigReason> initAtomMatchingTrackers(
1618         const StatsdConfig& config, const sp<UidMap>& uidMap,
1619         unordered_map<int64_t, int>& atomMatchingTrackerMap,
1620         vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
1621         unordered_map<int, vector<int>>& allTagIdsToMatchersMap) {
1622     vector<AtomMatcher> matcherConfigs;
1623     const int atomMatcherCount = config.atom_matcher_size();
1624     matcherConfigs.reserve(atomMatcherCount);
1625     allAtomMatchingTrackers.reserve(atomMatcherCount);
1626     optional<InvalidConfigReason> invalidConfigReason;
1627 
1628     for (int i = 0; i < atomMatcherCount; i++) {
1629         const AtomMatcher& logMatcher = config.atom_matcher(i);
1630         sp<AtomMatchingTracker> tracker =
1631                 createAtomMatchingTracker(logMatcher, uidMap, invalidConfigReason);
1632         if (tracker == nullptr) {
1633             return invalidConfigReason;
1634         }
1635         allAtomMatchingTrackers.push_back(tracker);
1636         if (atomMatchingTrackerMap.find(logMatcher.id()) != atomMatchingTrackerMap.end()) {
1637             ALOGE("Duplicate AtomMatcher found!");
1638             return createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_DUPLICATE,
1639                                                         logMatcher.id());
1640         }
1641         atomMatchingTrackerMap[logMatcher.id()] = i;
1642         matcherConfigs.push_back(logMatcher);
1643     }
1644 
1645     vector<uint8_t> stackTracker2(allAtomMatchingTrackers.size(), false);
1646     for (size_t matcherIndex = 0; matcherIndex < allAtomMatchingTrackers.size(); matcherIndex++) {
1647         auto& matcher = allAtomMatchingTrackers[matcherIndex];
1648         const auto [invalidConfigReason, _] =
1649                 matcher->init(matcherIndex, matcherConfigs, allAtomMatchingTrackers,
1650                               atomMatchingTrackerMap, stackTracker2);
1651         if (invalidConfigReason.has_value()) {
1652             return invalidConfigReason;
1653         }
1654 
1655         // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
1656         const set<int>& tagIds = matcher->getAtomIds();
1657         for (int atomId : tagIds) {
1658             auto& matchers = allTagIdsToMatchersMap[atomId];
1659             // Performance note:
1660             // For small amount of elements linear search in vector will be
1661             // faster then look up in a set:
1662             // - we do not expect matchers vector per atom id will have significant size (< 10)
1663             // - iteration via vector is the fastest way compared to other containers (set, etc.)
1664             //   in the hot path MetricsManager::onLogEvent()
1665             // - vector<T> will have the smallest memory footprint compared to any other
1666             //   std containers implementation
1667             if (find(matchers.begin(), matchers.end(), matcherIndex) == matchers.end()) {
1668                 matchers.push_back(matcherIndex);
1669             }
1670         }
1671     }
1672 
1673     return nullopt;
1674 }
1675 
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)1676 optional<InvalidConfigReason> initConditions(
1677         const ConfigKey& key, const StatsdConfig& config,
1678         const unordered_map<int64_t, int>& atomMatchingTrackerMap,
1679         unordered_map<int64_t, int>& conditionTrackerMap,
1680         vector<sp<ConditionTracker>>& allConditionTrackers,
1681         unordered_map<int, std::vector<int>>& trackerToConditionMap,
1682         vector<ConditionState>& initialConditionCache) {
1683     vector<Predicate> conditionConfigs;
1684     const int conditionTrackerCount = config.predicate_size();
1685     conditionConfigs.reserve(conditionTrackerCount);
1686     allConditionTrackers.reserve(conditionTrackerCount);
1687     initialConditionCache.assign(conditionTrackerCount, ConditionState::kNotEvaluated);
1688     optional<InvalidConfigReason> invalidConfigReason;
1689 
1690     for (int i = 0; i < conditionTrackerCount; i++) {
1691         const Predicate& condition = config.predicate(i);
1692         sp<ConditionTracker> tracker = createConditionTracker(
1693                 key, condition, i, atomMatchingTrackerMap, invalidConfigReason);
1694         if (tracker == nullptr) {
1695             return invalidConfigReason;
1696         }
1697         allConditionTrackers.push_back(tracker);
1698         if (conditionTrackerMap.find(condition.id()) != conditionTrackerMap.end()) {
1699             ALOGE("Duplicate Predicate found!");
1700             return createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_CONDITION_DUPLICATE,
1701                                                           condition.id());
1702         }
1703         conditionTrackerMap[condition.id()] = i;
1704         conditionConfigs.push_back(condition);
1705     }
1706 
1707     vector<uint8_t> stackTracker(allConditionTrackers.size(), false);
1708     for (size_t i = 0; i < allConditionTrackers.size(); i++) {
1709         auto& conditionTracker = allConditionTrackers[i];
1710         invalidConfigReason =
1711                 conditionTracker->init(conditionConfigs, allConditionTrackers, conditionTrackerMap,
1712                                        stackTracker, initialConditionCache);
1713         if (invalidConfigReason.has_value()) {
1714             return invalidConfigReason;
1715         }
1716         for (const int trackerIndex : conditionTracker->getAtomMatchingTrackerIndex()) {
1717             auto& conditionList = trackerToConditionMap[trackerIndex];
1718             conditionList.push_back(i);
1719         }
1720     }
1721     return nullopt;
1722 }
1723 
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)1724 optional<InvalidConfigReason> initStates(
1725         const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
1726         unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
1727         map<int64_t, uint64_t>& stateProtoHashes) {
1728     for (int i = 0; i < config.state_size(); i++) {
1729         const State& state = config.state(i);
1730         const int64_t stateId = state.id();
1731         stateAtomIdMap[stateId] = state.atom_id();
1732 
1733         string serializedState;
1734         if (!state.SerializeToString(&serializedState)) {
1735             ALOGE("Unable to serialize state %lld", (long long)stateId);
1736             return createInvalidConfigReasonWithState(
1737                     INVALID_CONFIG_REASON_STATE_SERIALIZATION_FAILED, state.id(), state.atom_id());
1738         }
1739         stateProtoHashes[stateId] = Hash64(serializedState);
1740 
1741         const StateMap& stateMap = state.map();
1742         for (const auto& group : stateMap.group()) {
1743             for (const auto& value : group.value()) {
1744                 allStateGroupMaps[stateId][value] = group.group_id();
1745             }
1746         }
1747     }
1748 
1749     return nullopt;
1750 }
1751 
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)1752 optional<InvalidConfigReason> initMetrics(
1753         const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
1754         const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
1755         const unordered_map<int64_t, int>& atomMatchingTrackerMap,
1756         const unordered_map<int64_t, int>& conditionTrackerMap,
1757         const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
1758         const unordered_map<int64_t, int>& stateAtomIdMap,
1759         const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
1760         vector<sp<ConditionTracker>>& allConditionTrackers,
1761         const vector<ConditionState>& initialConditionCache,
1762         vector<sp<MetricProducer>>& allMetricProducers,
1763         unordered_map<int, vector<int>>& conditionToMetricMap,
1764         unordered_map<int, vector<int>>& trackerToMetricMap, unordered_map<int64_t, int>& metricMap,
1765         std::set<int64_t>& noReportMetricIds,
1766         unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
1767         unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
1768         vector<int>& metricsWithActivation,
1769         const wp<ConfigMetadataProvider> configMetadataProvider) {
1770     sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
1771     sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchingTrackers);
1772     const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
1773                                 config.event_metric_size() + config.gauge_metric_size() +
1774                                 config.value_metric_size() + config.kll_metric_size();
1775     allMetricProducers.reserve(allMetricsCount);
1776     optional<InvalidConfigReason> invalidConfigReason;
1777 
1778     if (config.has_restricted_metrics_delegate_package_name() &&
1779         allMetricsCount != config.event_metric_size()) {
1780         ALOGE("Restricted metrics only support event metric");
1781         return InvalidConfigReason(INVALID_CONFIG_REASON_RESTRICTED_METRIC_NOT_SUPPORTED);
1782     }
1783 
1784     // Construct map from metric id to metric activation index. The map will be used to determine
1785     // the metric activation corresponding to a metric.
1786     unordered_map<int64_t, int> metricToActivationMap;
1787     for (int i = 0; i < config.metric_activation_size(); i++) {
1788         const MetricActivation& metricActivation = config.metric_activation(i);
1789         int64_t metricId = metricActivation.metric_id();
1790         if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) {
1791             ALOGE("Metric %lld has multiple MetricActivations", (long long)metricId);
1792             return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_HAS_MULTIPLE_ACTIVATIONS,
1793                                        metricId);
1794         }
1795         metricToActivationMap.insert({metricId, i});
1796     }
1797 
1798     // Build MetricProducers for each metric defined in config.
1799     // build CountMetricProducer
1800     for (int i = 0; i < config.count_metric_size(); i++) {
1801         int metricIndex = allMetricProducers.size();
1802         const CountMetric& metric = config.count_metric(i);
1803         metricMap.insert({metric.id(), metricIndex});
1804         optional<sp<MetricProducer>> producer = createCountMetricProducerAndUpdateMetadata(
1805                 key, config, timeBaseTimeNs, currentTimeNs, metric, metricIndex,
1806                 allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
1807                 conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
1808                 allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
1809                 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1810                 metricsWithActivation, invalidConfigReason, configMetadataProvider);
1811         if (!producer) {
1812             return invalidConfigReason;
1813         }
1814         allMetricProducers.push_back(producer.value());
1815     }
1816 
1817     // build DurationMetricProducer
1818     for (int i = 0; i < config.duration_metric_size(); i++) {
1819         int metricIndex = allMetricProducers.size();
1820         const DurationMetric& metric = config.duration_metric(i);
1821         metricMap.insert({metric.id(), metricIndex});
1822 
1823         optional<sp<MetricProducer>> producer = createDurationMetricProducerAndUpdateMetadata(
1824                 key, config, timeBaseTimeNs, currentTimeNs, metric, metricIndex,
1825                 allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
1826                 conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
1827                 allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
1828                 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1829                 metricsWithActivation, invalidConfigReason, configMetadataProvider);
1830         if (!producer) {
1831             return invalidConfigReason;
1832         }
1833         allMetricProducers.push_back(producer.value());
1834     }
1835 
1836     // build EventMetricProducer
1837     for (int i = 0; i < config.event_metric_size(); i++) {
1838         int metricIndex = allMetricProducers.size();
1839         const EventMetric& metric = config.event_metric(i);
1840         metricMap.insert({metric.id(), metricIndex});
1841         optional<sp<MetricProducer>> producer = createEventMetricProducerAndUpdateMetadata(
1842                 key, config, timeBaseTimeNs, metric, metricIndex, allAtomMatchingTrackers,
1843                 atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap,
1844                 initialConditionCache, wizard, stateAtomIdMap, allStateGroupMaps,
1845                 metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
1846                 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1847                 metricsWithActivation, invalidConfigReason, configMetadataProvider);
1848         if (!producer) {
1849             return invalidConfigReason;
1850         }
1851         allMetricProducers.push_back(producer.value());
1852     }
1853 
1854     // build NumericValueMetricProducer
1855     for (int i = 0; i < config.value_metric_size(); i++) {
1856         int metricIndex = allMetricProducers.size();
1857         const ValueMetric& metric = config.value_metric(i);
1858         metricMap.insert({metric.id(), metricIndex});
1859         optional<sp<MetricProducer>> producer = createNumericValueMetricProducerAndUpdateMetadata(
1860                 key, config, timeBaseTimeNs, currentTimeNs, pullerManager, metric, metricIndex,
1861                 allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
1862                 conditionTrackerMap, initialConditionCache, wizard, matcherWizard, stateAtomIdMap,
1863                 allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
1864                 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1865                 metricsWithActivation, invalidConfigReason, configMetadataProvider);
1866         if (!producer) {
1867             return invalidConfigReason;
1868         }
1869         allMetricProducers.push_back(producer.value());
1870     }
1871 
1872     // build KllMetricProducer
1873     for (int i = 0; i < config.kll_metric_size(); i++) {
1874         int metricIndex = allMetricProducers.size();
1875         const KllMetric& metric = config.kll_metric(i);
1876         metricMap.insert({metric.id(), metricIndex});
1877         optional<sp<MetricProducer>> producer = createKllMetricProducerAndUpdateMetadata(
1878                 key, config, timeBaseTimeNs, currentTimeNs, pullerManager, metric, metricIndex,
1879                 allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
1880                 conditionTrackerMap, initialConditionCache, wizard, matcherWizard, stateAtomIdMap,
1881                 allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
1882                 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1883                 metricsWithActivation, invalidConfigReason, configMetadataProvider);
1884         if (!producer) {
1885             return invalidConfigReason;
1886         }
1887         allMetricProducers.push_back(producer.value());
1888     }
1889 
1890     // Gauge metrics.
1891     for (int i = 0; i < config.gauge_metric_size(); i++) {
1892         int metricIndex = allMetricProducers.size();
1893         const GaugeMetric& metric = config.gauge_metric(i);
1894         metricMap.insert({metric.id(), metricIndex});
1895         optional<sp<MetricProducer>> producer = createGaugeMetricProducerAndUpdateMetadata(
1896                 key, config, timeBaseTimeNs, currentTimeNs, pullerManager, metric, metricIndex,
1897                 allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
1898                 conditionTrackerMap, initialConditionCache, wizard, matcherWizard, stateAtomIdMap,
1899                 allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
1900                 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
1901                 metricsWithActivation, invalidConfigReason, configMetadataProvider);
1902         if (!producer) {
1903             return invalidConfigReason;
1904         }
1905         allMetricProducers.push_back(producer.value());
1906     }
1907     for (int i = 0; i < config.no_report_metric_size(); ++i) {
1908         const auto no_report_metric = config.no_report_metric(i);
1909         if (metricMap.find(no_report_metric) == metricMap.end()) {
1910             ALOGW("no_report_metric %" PRId64 " not exist", no_report_metric);
1911             return InvalidConfigReason(INVALID_CONFIG_REASON_NO_REPORT_METRIC_NOT_FOUND,
1912                                        no_report_metric);
1913         }
1914         noReportMetricIds.insert(no_report_metric);
1915     }
1916 
1917     const set<int> whitelistedAtomIds(config.whitelisted_atom_ids().begin(),
1918                                       config.whitelisted_atom_ids().end());
1919     for (const auto& it : allMetricProducers) {
1920         // Register metrics to StateTrackers
1921         for (int atomId : it->getSlicedStateAtoms()) {
1922             // Register listener for non-whitelisted atoms only. Using whitelisted atom as a sliced
1923             // state atom is not allowed.
1924             if (whitelistedAtomIds.find(atomId) == whitelistedAtomIds.end()) {
1925                 StateManager::getInstance().registerListener(atomId, it);
1926             } else {
1927                 return InvalidConfigReason(
1928                         INVALID_CONFIG_REASON_METRIC_SLICED_STATE_ATOM_ALLOWED_FROM_ANY_UID,
1929                         it->getMetricId());
1930             }
1931         }
1932     }
1933     return nullopt;
1934 }
1935 
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)1936 optional<InvalidConfigReason> initAlerts(const StatsdConfig& config, const int64_t currentTimeNs,
1937                                          const unordered_map<int64_t, int>& metricProducerMap,
1938                                          unordered_map<int64_t, int>& alertTrackerMap,
1939                                          const sp<AlarmMonitor>& anomalyAlarmMonitor,
1940                                          vector<sp<MetricProducer>>& allMetricProducers,
1941                                          vector<sp<AnomalyTracker>>& allAnomalyTrackers) {
1942     optional<InvalidConfigReason> invalidConfigReason;
1943     for (int i = 0; i < config.alert_size(); i++) {
1944         const Alert& alert = config.alert(i);
1945         alertTrackerMap.insert(std::make_pair(alert.id(), allAnomalyTrackers.size()));
1946         optional<sp<AnomalyTracker>> anomalyTracker = createAnomalyTracker(
1947                 alert, anomalyAlarmMonitor, UpdateStatus::UPDATE_NEW, currentTimeNs,
1948                 metricProducerMap, allMetricProducers, invalidConfigReason);
1949         if (!anomalyTracker) {
1950             return invalidConfigReason;
1951         }
1952         allAnomalyTrackers.push_back(anomalyTracker.value());
1953     }
1954     return initSubscribersForSubscriptionType(config, Subscription::ALERT, alertTrackerMap,
1955                                               allAnomalyTrackers);
1956 }
1957 
initAlarms(const StatsdConfig & config,const ConfigKey & key,const sp<AlarmMonitor> & periodicAlarmMonitor,const int64_t timeBaseNs,const int64_t currentTimeNs,vector<sp<AlarmTracker>> & allAlarmTrackers)1958 optional<InvalidConfigReason> initAlarms(const StatsdConfig& config, const ConfigKey& key,
1959                                          const sp<AlarmMonitor>& periodicAlarmMonitor,
1960                                          const int64_t timeBaseNs, const int64_t currentTimeNs,
1961                                          vector<sp<AlarmTracker>>& allAlarmTrackers) {
1962     unordered_map<int64_t, int> alarmTrackerMap;
1963     int64_t startMillis = timeBaseNs / 1000 / 1000;
1964     int64_t currentTimeMillis = currentTimeNs / 1000 / 1000;
1965     for (int i = 0; i < config.alarm_size(); i++) {
1966         const Alarm& alarm = config.alarm(i);
1967         if (alarm.offset_millis() <= 0) {
1968             ALOGW("Alarm offset_millis should be larger than 0.");
1969             return createInvalidConfigReasonWithAlarm(
1970                     INVALID_CONFIG_REASON_ALARM_OFFSET_LESS_THAN_OR_EQUAL_ZERO, alarm.id());
1971         }
1972         if (alarm.period_millis() <= 0) {
1973             ALOGW("Alarm period_millis should be larger than 0.");
1974             return createInvalidConfigReasonWithAlarm(
1975                     INVALID_CONFIG_REASON_ALARM_PERIOD_LESS_THAN_OR_EQUAL_ZERO, alarm.id());
1976         }
1977         alarmTrackerMap.insert(std::make_pair(alarm.id(), allAlarmTrackers.size()));
1978         allAlarmTrackers.push_back(
1979                 new AlarmTracker(startMillis, currentTimeMillis, alarm, key, periodicAlarmMonitor));
1980     }
1981     return initSubscribersForSubscriptionType(config, Subscription::ALARM, alarmTrackerMap,
1982                                               allAlarmTrackers);
1983 }
1984 
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)1985 optional<InvalidConfigReason> initStatsdConfig(
1986         const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
1987         const sp<StatsPullerManager>& pullerManager, const sp<AlarmMonitor>& anomalyAlarmMonitor,
1988         const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
1989         const int64_t currentTimeNs, const wp<ConfigMetadataProvider> configMetadataProvider,
1990         std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
1991         vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
1992         unordered_map<int64_t, int>& atomMatchingTrackerMap,
1993         vector<sp<ConditionTracker>>& allConditionTrackers,
1994         unordered_map<int64_t, int>& conditionTrackerMap,
1995         vector<sp<MetricProducer>>& allMetricProducers,
1996         unordered_map<int64_t, int>& metricProducerMap,
1997         vector<sp<AnomalyTracker>>& allAnomalyTrackers,
1998         vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
1999         unordered_map<int, std::vector<int>>& conditionToMetricMap,
2000         unordered_map<int, std::vector<int>>& trackerToMetricMap,
2001         unordered_map<int, std::vector<int>>& trackerToConditionMap,
2002         unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
2003         unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
2004         unordered_map<int64_t, int>& alertTrackerMap, vector<int>& metricsWithActivation,
2005         map<int64_t, uint64_t>& stateProtoHashes, set<int64_t>& noReportMetricIds) {
2006     vector<ConditionState> initialConditionCache;
2007     unordered_map<int64_t, int> stateAtomIdMap;
2008     unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
2009 
2010     if (config.package_certificate_hash_size_bytes() > UINT8_MAX) {
2011         ALOGE("Invalid value for package_certificate_hash_size_bytes: %d",
2012               config.package_certificate_hash_size_bytes());
2013         return InvalidConfigReason(INVALID_CONFIG_REASON_PACKAGE_CERT_HASH_SIZE_TOO_LARGE);
2014     }
2015 
2016     optional<InvalidConfigReason> invalidConfigReason =
2017             initAtomMatchingTrackers(config, uidMap, atomMatchingTrackerMap,
2018                                      allAtomMatchingTrackers, allTagIdsToMatchersMap);
2019     if (invalidConfigReason.has_value()) {
2020         ALOGE("initAtomMatchingTrackers failed");
2021         return invalidConfigReason;
2022     }
2023     VLOG("initAtomMatchingTrackers succeed...");
2024 
2025     invalidConfigReason =
2026             initConditions(key, config, atomMatchingTrackerMap, conditionTrackerMap,
2027                            allConditionTrackers, trackerToConditionMap, initialConditionCache);
2028     if (invalidConfigReason.has_value()) {
2029         ALOGE("initConditionTrackers failed");
2030         return invalidConfigReason;
2031     }
2032 
2033     invalidConfigReason = initStates(config, stateAtomIdMap, allStateGroupMaps, stateProtoHashes);
2034     if (invalidConfigReason.has_value()) {
2035         ALOGE("initStates failed");
2036         return invalidConfigReason;
2037     }
2038 
2039     invalidConfigReason = initMetrics(
2040             key, config, timeBaseNs, currentTimeNs, pullerManager, atomMatchingTrackerMap,
2041             conditionTrackerMap, allAtomMatchingTrackers, stateAtomIdMap, allStateGroupMaps,
2042             allConditionTrackers, initialConditionCache, allMetricProducers, conditionToMetricMap,
2043             trackerToMetricMap, metricProducerMap, noReportMetricIds,
2044             activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
2045             metricsWithActivation, configMetadataProvider);
2046     if (invalidConfigReason.has_value()) {
2047         ALOGE("initMetricProducers failed");
2048         return invalidConfigReason;
2049     }
2050 
2051     invalidConfigReason = initAlerts(config, currentTimeNs, metricProducerMap, alertTrackerMap,
2052                                      anomalyAlarmMonitor, allMetricProducers, allAnomalyTrackers);
2053     if (invalidConfigReason.has_value()) {
2054         ALOGE("initAlerts failed");
2055         return invalidConfigReason;
2056     }
2057 
2058     invalidConfigReason = initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
2059                                      allPeriodicAlarmTrackers);
2060     if (invalidConfigReason.has_value()) {
2061         ALOGE("initAlarms failed");
2062         return invalidConfigReason;
2063     }
2064 
2065     return nullopt;
2066 }
2067 
2068 }  // namespace statsd
2069 }  // namespace os
2070 }  // namespace android
2071