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