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