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