1 /*
2 * Copyright (C) 2020 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 "config_update_utils.h"
21
22 #include "external/StatsPullerManager.h"
23 #include "hash.h"
24 #include "matchers/EventMatcherWizard.h"
25 #include "metrics_manager_util.h"
26
27 using google::protobuf::MessageLite;
28
29 namespace android {
30 namespace os {
31 namespace statsd {
32
33 // Recursive function to determine if a matcher needs to be updated. Populates matcherToUpdate.
34 // Returns nullopt if successful and InvalidConfigReason if not.
determineMatcherUpdateStatus(const StatsdConfig & config,const int matcherIdx,const unordered_map<int64_t,int> & oldAtomMatchingTrackerMap,const vector<sp<AtomMatchingTracker>> & oldAtomMatchingTrackers,const unordered_map<int64_t,int> & newAtomMatchingTrackerMap,vector<UpdateStatus> & matchersToUpdate,vector<uint8_t> & cycleTracker)35 optional<InvalidConfigReason> determineMatcherUpdateStatus(
36 const StatsdConfig& config, const int matcherIdx,
37 const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
38 const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
39 const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
40 vector<UpdateStatus>& matchersToUpdate, vector<uint8_t>& cycleTracker) {
41 // Have already examined this matcher.
42 if (matchersToUpdate[matcherIdx] != UPDATE_UNKNOWN) {
43 return nullopt;
44 }
45
46 const AtomMatcher& matcher = config.atom_matcher(matcherIdx);
47 int64_t id = matcher.id();
48 // Check if new matcher.
49 const auto& oldAtomMatchingTrackerIt = oldAtomMatchingTrackerMap.find(id);
50 if (oldAtomMatchingTrackerIt == oldAtomMatchingTrackerMap.end()) {
51 matchersToUpdate[matcherIdx] = UPDATE_NEW;
52 return nullopt;
53 }
54
55 // This is an existing matcher. Check if it has changed.
56 string serializedMatcher;
57 if (!matcher.SerializeToString(&serializedMatcher)) {
58 ALOGE("Unable to serialize matcher %lld", (long long)id);
59 return createInvalidConfigReasonWithMatcher(
60 INVALID_CONFIG_REASON_MATCHER_SERIALIZATION_FAILED, id);
61 }
62 uint64_t newProtoHash = Hash64(serializedMatcher);
63 if (newProtoHash != oldAtomMatchingTrackers[oldAtomMatchingTrackerIt->second]->getProtoHash()) {
64 matchersToUpdate[matcherIdx] = UPDATE_REPLACE;
65 return nullopt;
66 }
67
68 optional<InvalidConfigReason> invalidConfigReason;
69 switch (matcher.contents_case()) {
70 case AtomMatcher::ContentsCase::kSimpleAtomMatcher: {
71 matchersToUpdate[matcherIdx] = UPDATE_PRESERVE;
72 return nullopt;
73 }
74 case AtomMatcher::ContentsCase::kCombination: {
75 // Recurse to check if children have changed.
76 cycleTracker[matcherIdx] = true;
77 UpdateStatus status = UPDATE_PRESERVE;
78 for (const int64_t childMatcherId : matcher.combination().matcher()) {
79 const auto& childIt = newAtomMatchingTrackerMap.find(childMatcherId);
80 if (childIt == newAtomMatchingTrackerMap.end()) {
81 ALOGW("Matcher %lld not found in the config", (long long)childMatcherId);
82 invalidConfigReason = createInvalidConfigReasonWithMatcher(
83 INVALID_CONFIG_REASON_MATCHER_CHILD_NOT_FOUND, id);
84 invalidConfigReason->matcherIds.push_back(childMatcherId);
85 return invalidConfigReason;
86 }
87 const int childIdx = childIt->second;
88 if (cycleTracker[childIdx]) {
89 ALOGE("Cycle detected in matcher config");
90 invalidConfigReason = createInvalidConfigReasonWithMatcher(
91 INVALID_CONFIG_REASON_MATCHER_CYCLE, id);
92 invalidConfigReason->matcherIds.push_back(childMatcherId);
93 return invalidConfigReason;
94 }
95 invalidConfigReason = determineMatcherUpdateStatus(
96 config, childIdx, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers,
97 newAtomMatchingTrackerMap, matchersToUpdate, cycleTracker);
98 if (invalidConfigReason.has_value()) {
99 invalidConfigReason->matcherIds.push_back(id);
100 return invalidConfigReason;
101 }
102
103 if (matchersToUpdate[childIdx] == UPDATE_REPLACE) {
104 status = UPDATE_REPLACE;
105 break;
106 }
107 }
108 matchersToUpdate[matcherIdx] = status;
109 cycleTracker[matcherIdx] = false;
110 return nullopt;
111 }
112 default: {
113 ALOGE("Matcher \"%lld\" malformed", (long long)id);
114 return createInvalidConfigReasonWithMatcher(
115 INVALID_CONFIG_REASON_MATCHER_MALFORMED_CONTENTS_CASE, id);
116 }
117 }
118 return nullopt;
119 }
120
updateAtomMatchingTrackers(const StatsdConfig & config,const sp<UidMap> & uidMap,const unordered_map<int64_t,int> & oldAtomMatchingTrackerMap,const vector<sp<AtomMatchingTracker>> & oldAtomMatchingTrackers,std::unordered_map<int,std::vector<int>> & allTagIdsToMatchersMap,unordered_map<int64_t,int> & newAtomMatchingTrackerMap,vector<sp<AtomMatchingTracker>> & newAtomMatchingTrackers,set<int64_t> & replacedMatchers)121 optional<InvalidConfigReason> updateAtomMatchingTrackers(
122 const StatsdConfig& config, const sp<UidMap>& uidMap,
123 const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
124 const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
125 std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
126 unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
127 vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers, set<int64_t>& replacedMatchers) {
128 const int atomMatcherCount = config.atom_matcher_size();
129 vector<AtomMatcher> matcherProtos;
130 matcherProtos.reserve(atomMatcherCount);
131 newAtomMatchingTrackers.reserve(atomMatcherCount);
132 optional<InvalidConfigReason> invalidConfigReason;
133
134 // Maps matcher id to their position in the config. For fast lookup of dependencies.
135 for (int i = 0; i < atomMatcherCount; i++) {
136 const AtomMatcher& matcher = config.atom_matcher(i);
137 if (newAtomMatchingTrackerMap.find(matcher.id()) != newAtomMatchingTrackerMap.end()) {
138 ALOGE("Duplicate atom matcher found for id %lld", (long long)matcher.id());
139 return createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_DUPLICATE,
140 matcher.id());
141 }
142 newAtomMatchingTrackerMap[matcher.id()] = i;
143 matcherProtos.push_back(matcher);
144 }
145
146 // For combination matchers, we need to determine if any children need to be updated.
147 vector<UpdateStatus> matchersToUpdate(atomMatcherCount, UPDATE_UNKNOWN);
148 vector<uint8_t> cycleTracker(atomMatcherCount, false);
149 for (int i = 0; i < atomMatcherCount; i++) {
150 invalidConfigReason = determineMatcherUpdateStatus(
151 config, i, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers,
152 newAtomMatchingTrackerMap, matchersToUpdate, cycleTracker);
153 if (invalidConfigReason.has_value()) {
154 return invalidConfigReason;
155 }
156 }
157
158 for (int i = 0; i < atomMatcherCount; i++) {
159 const AtomMatcher& matcher = config.atom_matcher(i);
160 const int64_t id = matcher.id();
161 switch (matchersToUpdate[i]) {
162 case UPDATE_PRESERVE: {
163 const auto& oldAtomMatchingTrackerIt = oldAtomMatchingTrackerMap.find(id);
164 if (oldAtomMatchingTrackerIt == oldAtomMatchingTrackerMap.end()) {
165 ALOGE("Could not find AtomMatcher %lld in the previous config, but expected it "
166 "to be there",
167 (long long)id);
168 return createInvalidConfigReasonWithMatcher(
169 INVALID_CONFIG_REASON_MATCHER_NOT_IN_PREV_CONFIG, id);
170 }
171 const sp<AtomMatchingTracker>& tracker =
172 oldAtomMatchingTrackers[oldAtomMatchingTrackerIt->second];
173 invalidConfigReason =
174 tracker->onConfigUpdated(matcherProtos[i], newAtomMatchingTrackerMap);
175 if (invalidConfigReason.has_value()) {
176 ALOGW("Config update failed for matcher %lld", (long long)id);
177 return invalidConfigReason;
178 }
179 newAtomMatchingTrackers.push_back(tracker);
180 break;
181 }
182 case UPDATE_REPLACE:
183 replacedMatchers.insert(id);
184 [[fallthrough]]; // Intentionally fallthrough to create the new matcher.
185 case UPDATE_NEW: {
186 sp<AtomMatchingTracker> tracker =
187 createAtomMatchingTracker(matcher, uidMap, invalidConfigReason);
188 if (tracker == nullptr) {
189 return invalidConfigReason;
190 }
191 newAtomMatchingTrackers.push_back(tracker);
192 break;
193 }
194 default: {
195 ALOGE("Matcher \"%lld\" update state is unknown. This should never happen",
196 (long long)id);
197 return createInvalidConfigReasonWithMatcher(
198 INVALID_CONFIG_REASON_MATCHER_UPDATE_STATUS_UNKNOWN, id);
199 }
200 }
201 }
202
203 std::fill(cycleTracker.begin(), cycleTracker.end(), false);
204 for (size_t matcherIndex = 0; matcherIndex < newAtomMatchingTrackers.size(); matcherIndex++) {
205 auto& matcher = newAtomMatchingTrackers[matcherIndex];
206 const auto [invalidConfigReason, _] =
207 matcher->init(matcherIndex, matcherProtos, newAtomMatchingTrackers,
208 newAtomMatchingTrackerMap, cycleTracker);
209 if (invalidConfigReason.has_value()) {
210 return invalidConfigReason;
211 }
212
213 // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
214 const set<int>& tagIds = matcher->getAtomIds();
215 for (int atomId : tagIds) {
216 auto& matchers = allTagIdsToMatchersMap[atomId];
217 // Performance note:
218 // For small amount of elements linear search in vector will be
219 // faster then look up in a set:
220 // - we do not expect matchers vector per atom id will have significant size (< 10)
221 // - iteration via vector is the fastest way compared to other containers (set, etc.)
222 // in the hot path MetricsManager::onLogEvent()
223 // - vector<T> will have the smallest memory footprint compared to any other
224 // std containers implementation
225 if (find(matchers.begin(), matchers.end(), matcherIndex) == matchers.end()) {
226 matchers.push_back(matcherIndex);
227 }
228 }
229 }
230
231 return nullopt;
232 }
233
234 // Recursive function to determine if a condition needs to be updated. Populates conditionsToUpdate.
235 // Returns nullopt if successful and InvalidConfigReason if not.
determineConditionUpdateStatus(const StatsdConfig & config,const int conditionIdx,const unordered_map<int64_t,int> & oldConditionTrackerMap,const vector<sp<ConditionTracker>> & oldConditionTrackers,const unordered_map<int64_t,int> & newConditionTrackerMap,const set<int64_t> & replacedMatchers,vector<UpdateStatus> & conditionsToUpdate,vector<uint8_t> & cycleTracker)236 optional<InvalidConfigReason> determineConditionUpdateStatus(
237 const StatsdConfig& config, const int conditionIdx,
238 const unordered_map<int64_t, int>& oldConditionTrackerMap,
239 const vector<sp<ConditionTracker>>& oldConditionTrackers,
240 const unordered_map<int64_t, int>& newConditionTrackerMap,
241 const set<int64_t>& replacedMatchers, vector<UpdateStatus>& conditionsToUpdate,
242 vector<uint8_t>& cycleTracker) {
243 // Have already examined this condition.
244 if (conditionsToUpdate[conditionIdx] != UPDATE_UNKNOWN) {
245 return nullopt;
246 }
247
248 const Predicate& predicate = config.predicate(conditionIdx);
249 int64_t id = predicate.id();
250 // Check if new condition.
251 const auto& oldConditionTrackerIt = oldConditionTrackerMap.find(id);
252 if (oldConditionTrackerIt == oldConditionTrackerMap.end()) {
253 conditionsToUpdate[conditionIdx] = UPDATE_NEW;
254 return nullopt;
255 }
256
257 // This is an existing condition. Check if it has changed.
258 string serializedCondition;
259 if (!predicate.SerializeToString(&serializedCondition)) {
260 ALOGE("Unable to serialize predicate %lld", (long long)id);
261 return createInvalidConfigReasonWithPredicate(
262 INVALID_CONFIG_REASON_CONDITION_SERIALIZATION_FAILED, id);
263 }
264 uint64_t newProtoHash = Hash64(serializedCondition);
265 if (newProtoHash != oldConditionTrackers[oldConditionTrackerIt->second]->getProtoHash()) {
266 conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
267 return nullopt;
268 }
269
270 optional<InvalidConfigReason> invalidConfigReason;
271 switch (predicate.contents_case()) {
272 case Predicate::ContentsCase::kSimplePredicate: {
273 // Need to check if any of the underlying matchers changed.
274 const SimplePredicate& simplePredicate = predicate.simple_predicate();
275 if (simplePredicate.has_start()) {
276 if (replacedMatchers.find(simplePredicate.start()) != replacedMatchers.end()) {
277 conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
278 return nullopt;
279 }
280 }
281 if (simplePredicate.has_stop()) {
282 if (replacedMatchers.find(simplePredicate.stop()) != replacedMatchers.end()) {
283 conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
284 return nullopt;
285 }
286 }
287 if (simplePredicate.has_stop_all()) {
288 if (replacedMatchers.find(simplePredicate.stop_all()) != replacedMatchers.end()) {
289 conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
290 return nullopt;
291 }
292 }
293 conditionsToUpdate[conditionIdx] = UPDATE_PRESERVE;
294 return nullopt;
295 }
296 case Predicate::ContentsCase::kCombination: {
297 // Need to recurse on the children to see if any of the child predicates changed.
298 cycleTracker[conditionIdx] = true;
299 UpdateStatus status = UPDATE_PRESERVE;
300 for (const int64_t childPredicateId : predicate.combination().predicate()) {
301 const auto& childIt = newConditionTrackerMap.find(childPredicateId);
302 if (childIt == newConditionTrackerMap.end()) {
303 ALOGW("Predicate %lld not found in the config", (long long)childPredicateId);
304 invalidConfigReason = createInvalidConfigReasonWithPredicate(
305 INVALID_CONFIG_REASON_CONDITION_CHILD_NOT_FOUND, id);
306 invalidConfigReason->conditionIds.push_back(childPredicateId);
307 return invalidConfigReason;
308 }
309 const int childIdx = childIt->second;
310 if (cycleTracker[childIdx]) {
311 ALOGE("Cycle detected in predicate config");
312 invalidConfigReason = createInvalidConfigReasonWithPredicate(
313 INVALID_CONFIG_REASON_CONDITION_CYCLE, id);
314 invalidConfigReason->conditionIds.push_back(childPredicateId);
315 return invalidConfigReason;
316 }
317 invalidConfigReason = determineConditionUpdateStatus(
318 config, childIdx, oldConditionTrackerMap, oldConditionTrackers,
319 newConditionTrackerMap, replacedMatchers, conditionsToUpdate, cycleTracker);
320 if (invalidConfigReason.has_value()) {
321 invalidConfigReason->conditionIds.push_back(id);
322 return invalidConfigReason;
323 }
324
325 if (conditionsToUpdate[childIdx] == UPDATE_REPLACE) {
326 status = UPDATE_REPLACE;
327 break;
328 }
329 }
330 conditionsToUpdate[conditionIdx] = status;
331 cycleTracker[conditionIdx] = false;
332 return nullopt;
333 }
334 default: {
335 ALOGE("Predicate \"%lld\" malformed", (long long)id);
336 return createInvalidConfigReasonWithPredicate(
337 INVALID_CONFIG_REASON_CONDITION_MALFORMED_CONTENTS_CASE, id);
338 }
339 }
340
341 return nullopt;
342 }
343
updateConditions(const ConfigKey & key,const StatsdConfig & config,const unordered_map<int64_t,int> & atomMatchingTrackerMap,const set<int64_t> & replacedMatchers,const unordered_map<int64_t,int> & oldConditionTrackerMap,const vector<sp<ConditionTracker>> & oldConditionTrackers,unordered_map<int64_t,int> & newConditionTrackerMap,vector<sp<ConditionTracker>> & newConditionTrackers,unordered_map<int,vector<int>> & trackerToConditionMap,vector<ConditionState> & conditionCache,set<int64_t> & replacedConditions)344 optional<InvalidConfigReason> updateConditions(
345 const ConfigKey& key, const StatsdConfig& config,
346 const unordered_map<int64_t, int>& atomMatchingTrackerMap,
347 const set<int64_t>& replacedMatchers,
348 const unordered_map<int64_t, int>& oldConditionTrackerMap,
349 const vector<sp<ConditionTracker>>& oldConditionTrackers,
350 unordered_map<int64_t, int>& newConditionTrackerMap,
351 vector<sp<ConditionTracker>>& newConditionTrackers,
352 unordered_map<int, vector<int>>& trackerToConditionMap,
353 vector<ConditionState>& conditionCache, set<int64_t>& replacedConditions) {
354 vector<Predicate> conditionProtos;
355 const int conditionTrackerCount = config.predicate_size();
356 conditionProtos.reserve(conditionTrackerCount);
357 newConditionTrackers.reserve(conditionTrackerCount);
358 conditionCache.assign(conditionTrackerCount, ConditionState::kNotEvaluated);
359 optional<InvalidConfigReason> invalidConfigReason;
360
361 for (int i = 0; i < conditionTrackerCount; i++) {
362 const Predicate& condition = config.predicate(i);
363 if (newConditionTrackerMap.find(condition.id()) != newConditionTrackerMap.end()) {
364 ALOGE("Duplicate Predicate found!");
365 return createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_CONDITION_DUPLICATE,
366 condition.id());
367 }
368 newConditionTrackerMap[condition.id()] = i;
369 conditionProtos.push_back(condition);
370 }
371
372 vector<UpdateStatus> conditionsToUpdate(conditionTrackerCount, UPDATE_UNKNOWN);
373 vector<uint8_t> cycleTracker(conditionTrackerCount, false);
374 for (int i = 0; i < conditionTrackerCount; i++) {
375 invalidConfigReason = determineConditionUpdateStatus(
376 config, i, oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap,
377 replacedMatchers, conditionsToUpdate, cycleTracker);
378 if (invalidConfigReason.has_value()) {
379 return invalidConfigReason;
380 }
381 }
382
383 // Update status has been determined for all conditions. Now perform the update.
384 set<int> preservedConditions;
385 for (int i = 0; i < conditionTrackerCount; i++) {
386 const Predicate& predicate = config.predicate(i);
387 const int64_t id = predicate.id();
388 switch (conditionsToUpdate[i]) {
389 case UPDATE_PRESERVE: {
390 preservedConditions.insert(i);
391 const auto& oldConditionTrackerIt = oldConditionTrackerMap.find(id);
392 if (oldConditionTrackerIt == oldConditionTrackerMap.end()) {
393 ALOGE("Could not find Predicate %lld in the previous config, but expected it "
394 "to be there",
395 (long long)id);
396 return createInvalidConfigReasonWithPredicate(
397 INVALID_CONFIG_REASON_CONDITION_NOT_IN_PREV_CONFIG, id);
398 }
399 const int oldIndex = oldConditionTrackerIt->second;
400 newConditionTrackers.push_back(oldConditionTrackers[oldIndex]);
401 break;
402 }
403 case UPDATE_REPLACE:
404 replacedConditions.insert(id);
405 [[fallthrough]]; // Intentionally fallthrough to create the new condition tracker.
406 case UPDATE_NEW: {
407 sp<ConditionTracker> tracker = createConditionTracker(
408 key, predicate, i, atomMatchingTrackerMap, invalidConfigReason);
409 if (tracker == nullptr) {
410 return invalidConfigReason;
411 }
412 newConditionTrackers.push_back(tracker);
413 break;
414 }
415 default: {
416 ALOGE("Condition \"%lld\" update state is unknown. This should never happen",
417 (long long)id);
418 return createInvalidConfigReasonWithPredicate(
419 INVALID_CONFIG_REASON_CONDITION_UPDATE_STATUS_UNKNOWN, id);
420 }
421 }
422 }
423
424 // Update indices of preserved predicates.
425 for (const int conditionIndex : preservedConditions) {
426 invalidConfigReason = newConditionTrackers[conditionIndex]->onConfigUpdated(
427 conditionProtos, conditionIndex, newConditionTrackers, atomMatchingTrackerMap,
428 newConditionTrackerMap);
429 if (invalidConfigReason.has_value()) {
430 ALOGE("Failed to update condition %lld",
431 (long long)newConditionTrackers[conditionIndex]->getConditionId());
432 return invalidConfigReason;
433 }
434 }
435
436 std::fill(cycleTracker.begin(), cycleTracker.end(), false);
437 for (int conditionIndex = 0; conditionIndex < conditionTrackerCount; conditionIndex++) {
438 const sp<ConditionTracker>& conditionTracker = newConditionTrackers[conditionIndex];
439 // Calling init on preserved conditions is OK. It is needed to fill the condition cache.
440 invalidConfigReason =
441 conditionTracker->init(conditionProtos, newConditionTrackers,
442 newConditionTrackerMap, cycleTracker, conditionCache);
443 if (invalidConfigReason.has_value()) {
444 return invalidConfigReason;
445 }
446 for (const int trackerIndex : conditionTracker->getAtomMatchingTrackerIndex()) {
447 vector<int>& conditionList = trackerToConditionMap[trackerIndex];
448 conditionList.push_back(conditionIndex);
449 }
450 }
451 return nullopt;
452 }
453
updateStates(const StatsdConfig & config,const map<int64_t,uint64_t> & oldStateProtoHashes,unordered_map<int64_t,int> & stateAtomIdMap,unordered_map<int64_t,unordered_map<int,int64_t>> & allStateGroupMaps,map<int64_t,uint64_t> & newStateProtoHashes,set<int64_t> & replacedStates)454 optional<InvalidConfigReason> updateStates(
455 const StatsdConfig& config, const map<int64_t, uint64_t>& oldStateProtoHashes,
456 unordered_map<int64_t, int>& stateAtomIdMap,
457 unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
458 map<int64_t, uint64_t>& newStateProtoHashes, set<int64_t>& replacedStates) {
459 // Share with metrics_manager_util.
460 optional<InvalidConfigReason> invalidConfigReason =
461 initStates(config, stateAtomIdMap, allStateGroupMaps, newStateProtoHashes);
462 if (invalidConfigReason.has_value()) {
463 return invalidConfigReason;
464 }
465
466 for (const auto& [stateId, stateHash] : oldStateProtoHashes) {
467 const auto& it = newStateProtoHashes.find(stateId);
468 if (it != newStateProtoHashes.end() && it->second != stateHash) {
469 replacedStates.insert(stateId);
470 }
471 }
472 return nullopt;
473 }
474 // Returns true if any matchers in the metric activation were replaced.
metricActivationDepsChange(const StatsdConfig & config,const unordered_map<int64_t,int> & metricToActivationMap,const int64_t metricId,const set<int64_t> & replacedMatchers)475 bool metricActivationDepsChange(const StatsdConfig& config,
476 const unordered_map<int64_t, int>& metricToActivationMap,
477 const int64_t metricId, const set<int64_t>& replacedMatchers) {
478 const auto& metricActivationIt = metricToActivationMap.find(metricId);
479 if (metricActivationIt == metricToActivationMap.end()) {
480 return false;
481 }
482 const MetricActivation& metricActivation = config.metric_activation(metricActivationIt->second);
483 for (int i = 0; i < metricActivation.event_activation_size(); i++) {
484 const EventActivation& activation = metricActivation.event_activation(i);
485 if (replacedMatchers.find(activation.atom_matcher_id()) != replacedMatchers.end()) {
486 return true;
487 }
488 if (activation.has_deactivation_atom_matcher_id()) {
489 if (replacedMatchers.find(activation.deactivation_atom_matcher_id()) !=
490 replacedMatchers.end()) {
491 return true;
492 }
493 }
494 }
495 return false;
496 }
497
determineMetricUpdateStatus(const StatsdConfig & config,const MessageLite & metric,const int64_t metricId,const MetricType metricType,const set<int64_t> & matcherDependencies,const set<int64_t> & conditionDependencies,const::google::protobuf::RepeatedField<int64_t> & stateDependencies,const::google::protobuf::RepeatedPtrField<MetricConditionLink> & conditionLinks,const unordered_map<int64_t,int> & oldMetricProducerMap,const vector<sp<MetricProducer>> & oldMetricProducers,const unordered_map<int64_t,int> & metricToActivationMap,const set<int64_t> & replacedMatchers,const set<int64_t> & replacedConditions,const set<int64_t> & replacedStates,UpdateStatus & updateStatus)498 optional<InvalidConfigReason> determineMetricUpdateStatus(
499 const StatsdConfig& config, const MessageLite& metric, const int64_t metricId,
500 const MetricType metricType, const set<int64_t>& matcherDependencies,
501 const set<int64_t>& conditionDependencies,
502 const ::google::protobuf::RepeatedField<int64_t>& stateDependencies,
503 const ::google::protobuf::RepeatedPtrField<MetricConditionLink>& conditionLinks,
504 const unordered_map<int64_t, int>& oldMetricProducerMap,
505 const vector<sp<MetricProducer>>& oldMetricProducers,
506 const unordered_map<int64_t, int>& metricToActivationMap,
507 const set<int64_t>& replacedMatchers, const set<int64_t>& replacedConditions,
508 const set<int64_t>& replacedStates, UpdateStatus& updateStatus) {
509 // Check if new metric
510 const auto& oldMetricProducerIt = oldMetricProducerMap.find(metricId);
511 if (oldMetricProducerIt == oldMetricProducerMap.end()) {
512 updateStatus = UPDATE_NEW;
513 return nullopt;
514 }
515
516 // This is an existing metric, check if it has changed.
517 uint64_t metricHash;
518 optional<InvalidConfigReason> invalidConfigReason =
519 getMetricProtoHash(config, metric, metricId, metricToActivationMap, metricHash);
520 if (invalidConfigReason.has_value()) {
521 return invalidConfigReason;
522 }
523 const sp<MetricProducer>& oldMetricProducer = oldMetricProducers[oldMetricProducerIt->second];
524 if (oldMetricProducer->getMetricType() != metricType ||
525 oldMetricProducer->getProtoHash() != metricHash) {
526 updateStatus = UPDATE_REPLACE;
527 return nullopt;
528 }
529
530 // Take intersections of the matchers/predicates/states that the metric
531 // depends on with those that have been replaced. If a metric depends on any
532 // replaced component, it too must be replaced.
533 set<int64_t> intersection;
534 set_intersection(matcherDependencies.begin(), matcherDependencies.end(),
535 replacedMatchers.begin(), replacedMatchers.end(),
536 inserter(intersection, intersection.begin()));
537 if (intersection.size() > 0) {
538 updateStatus = UPDATE_REPLACE;
539 return nullopt;
540 }
541 set_intersection(conditionDependencies.begin(), conditionDependencies.end(),
542 replacedConditions.begin(), replacedConditions.end(),
543 inserter(intersection, intersection.begin()));
544 if (intersection.size() > 0) {
545 updateStatus = UPDATE_REPLACE;
546 return nullopt;
547 }
548 set_intersection(stateDependencies.begin(), stateDependencies.end(), replacedStates.begin(),
549 replacedStates.end(), inserter(intersection, intersection.begin()));
550 if (intersection.size() > 0) {
551 updateStatus = UPDATE_REPLACE;
552 return nullopt;
553 }
554
555 for (const auto& metricConditionLink : conditionLinks) {
556 if (replacedConditions.find(metricConditionLink.condition()) != replacedConditions.end()) {
557 updateStatus = UPDATE_REPLACE;
558 return nullopt;
559 }
560 }
561
562 if (metricActivationDepsChange(config, metricToActivationMap, metricId, replacedMatchers)) {
563 updateStatus = UPDATE_REPLACE;
564 return nullopt;
565 }
566
567 updateStatus = UPDATE_PRESERVE;
568 return nullopt;
569 }
570
determineAllMetricUpdateStatuses(const StatsdConfig & config,const unordered_map<int64_t,int> & oldMetricProducerMap,const vector<sp<MetricProducer>> & oldMetricProducers,const unordered_map<int64_t,int> & metricToActivationMap,const set<int64_t> & replacedMatchers,const set<int64_t> & replacedConditions,const set<int64_t> & replacedStates,vector<UpdateStatus> & metricsToUpdate)571 optional<InvalidConfigReason> determineAllMetricUpdateStatuses(
572 const StatsdConfig& config, const unordered_map<int64_t, int>& oldMetricProducerMap,
573 const vector<sp<MetricProducer>>& oldMetricProducers,
574 const unordered_map<int64_t, int>& metricToActivationMap,
575 const set<int64_t>& replacedMatchers, const set<int64_t>& replacedConditions,
576 const set<int64_t>& replacedStates, vector<UpdateStatus>& metricsToUpdate) {
577 int metricIndex = 0;
578 optional<InvalidConfigReason> invalidConfigReason;
579 for (int i = 0; i < config.count_metric_size(); i++, metricIndex++) {
580 const CountMetric& metric = config.count_metric(i);
581 set<int64_t> conditionDependencies;
582 if (metric.has_condition()) {
583 conditionDependencies.insert(metric.condition());
584 }
585 invalidConfigReason = determineMetricUpdateStatus(
586 config, metric, metric.id(), METRIC_TYPE_COUNT, {metric.what()},
587 conditionDependencies, metric.slice_by_state(), metric.links(),
588 oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
589 replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
590 if (invalidConfigReason.has_value()) {
591 return invalidConfigReason;
592 }
593 }
594 for (int i = 0; i < config.duration_metric_size(); i++, metricIndex++) {
595 const DurationMetric& metric = config.duration_metric(i);
596 set<int64_t> conditionDependencies({metric.what()});
597 if (metric.has_condition()) {
598 conditionDependencies.insert(metric.condition());
599 }
600 invalidConfigReason = determineMetricUpdateStatus(
601 config, metric, metric.id(), METRIC_TYPE_DURATION, /*matcherDependencies=*/{},
602 conditionDependencies, metric.slice_by_state(), metric.links(),
603 oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
604 replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
605 if (invalidConfigReason.has_value()) {
606 return invalidConfigReason;
607 }
608 }
609 for (int i = 0; i < config.event_metric_size(); i++, metricIndex++) {
610 const EventMetric& metric = config.event_metric(i);
611 set<int64_t> conditionDependencies;
612 if (metric.has_condition()) {
613 conditionDependencies.insert(metric.condition());
614 }
615 invalidConfigReason = determineMetricUpdateStatus(
616 config, metric, metric.id(), METRIC_TYPE_EVENT, {metric.what()},
617 conditionDependencies, ::google::protobuf::RepeatedField<int64_t>(), metric.links(),
618 oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
619 replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
620 if (invalidConfigReason.has_value()) {
621 return invalidConfigReason;
622 }
623 }
624 for (int i = 0; i < config.value_metric_size(); i++, metricIndex++) {
625 const ValueMetric& metric = config.value_metric(i);
626 set<int64_t> conditionDependencies;
627 if (metric.has_condition()) {
628 conditionDependencies.insert(metric.condition());
629 }
630 invalidConfigReason = determineMetricUpdateStatus(
631 config, metric, metric.id(), METRIC_TYPE_VALUE, {metric.what()},
632 conditionDependencies, metric.slice_by_state(), metric.links(),
633 oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
634 replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
635 if (invalidConfigReason.has_value()) {
636 return invalidConfigReason;
637 }
638 }
639 for (int i = 0; i < config.gauge_metric_size(); i++, metricIndex++) {
640 const GaugeMetric& metric = config.gauge_metric(i);
641 set<int64_t> conditionDependencies;
642 if (metric.has_condition()) {
643 conditionDependencies.insert(metric.condition());
644 }
645 set<int64_t> matcherDependencies({metric.what()});
646 if (metric.has_trigger_event()) {
647 matcherDependencies.insert(metric.trigger_event());
648 }
649 invalidConfigReason = determineMetricUpdateStatus(
650 config, metric, metric.id(), METRIC_TYPE_GAUGE, matcherDependencies,
651 conditionDependencies, ::google::protobuf::RepeatedField<int64_t>(), metric.links(),
652 oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
653 replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
654 if (invalidConfigReason.has_value()) {
655 return invalidConfigReason;
656 }
657 }
658
659 for (int i = 0; i < config.kll_metric_size(); i++, metricIndex++) {
660 const KllMetric& metric = config.kll_metric(i);
661 set<int64_t> conditionDependencies;
662 if (metric.has_condition()) {
663 conditionDependencies.insert(metric.condition());
664 }
665 invalidConfigReason = determineMetricUpdateStatus(
666 config, metric, metric.id(), METRIC_TYPE_KLL, {metric.what()},
667 conditionDependencies, metric.slice_by_state(), metric.links(),
668 oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
669 replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
670 if (invalidConfigReason.has_value()) {
671 return invalidConfigReason;
672 }
673 }
674
675 return nullopt;
676 }
677
678 // Called when a metric is preserved during a config update. Finds the metric in oldMetricProducers
679 // and calls onConfigUpdated to update all indices.
updateMetric(const StatsdConfig & config,const int configIndex,const int metricIndex,const int64_t metricId,const vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,const unordered_map<int64_t,int> & oldAtomMatchingTrackerMap,const unordered_map<int64_t,int> & newAtomMatchingTrackerMap,const sp<EventMatcherWizard> & matcherWizard,const vector<sp<ConditionTracker>> & allConditionTrackers,const unordered_map<int64_t,int> & conditionTrackerMap,const sp<ConditionWizard> & wizard,const unordered_map<int64_t,int> & oldMetricProducerMap,const vector<sp<MetricProducer>> & oldMetricProducers,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)680 optional<sp<MetricProducer>> updateMetric(
681 const StatsdConfig& config, const int configIndex, const int metricIndex,
682 const int64_t metricId, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
683 const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
684 const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
685 const sp<EventMatcherWizard>& matcherWizard,
686 const vector<sp<ConditionTracker>>& allConditionTrackers,
687 const unordered_map<int64_t, int>& conditionTrackerMap, const sp<ConditionWizard>& wizard,
688 const unordered_map<int64_t, int>& oldMetricProducerMap,
689 const vector<sp<MetricProducer>>& oldMetricProducers,
690 const unordered_map<int64_t, int>& metricToActivationMap,
691 unordered_map<int, vector<int>>& trackerToMetricMap,
692 unordered_map<int, vector<int>>& conditionToMetricMap,
693 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
694 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
695 vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason) {
696 const auto& oldMetricProducerIt = oldMetricProducerMap.find(metricId);
697 if (oldMetricProducerIt == oldMetricProducerMap.end()) {
698 ALOGE("Could not find Metric %lld in the previous config, but expected it "
699 "to be there",
700 (long long)metricId);
701 invalidConfigReason =
702 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_NOT_IN_PREV_CONFIG, metricId);
703 return nullopt;
704 }
705 const int oldIndex = oldMetricProducerIt->second;
706 sp<MetricProducer> producer = oldMetricProducers[oldIndex];
707 invalidConfigReason = producer->onConfigUpdated(
708 config, configIndex, metricIndex, allAtomMatchingTrackers, oldAtomMatchingTrackerMap,
709 newAtomMatchingTrackerMap, matcherWizard, allConditionTrackers, conditionTrackerMap,
710 wizard, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
711 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
712 metricsWithActivation);
713 if (invalidConfigReason.has_value()) {
714 return nullopt;
715 }
716 return {producer};
717 }
718
updateMetrics(const ConfigKey & key,const StatsdConfig & config,const int64_t timeBaseNs,const int64_t currentTimeNs,const sp<StatsPullerManager> & pullerManager,const unordered_map<int64_t,int> & oldAtomMatchingTrackerMap,const unordered_map<int64_t,int> & newAtomMatchingTrackerMap,const set<int64_t> & replacedMatchers,const vector<sp<AtomMatchingTracker>> & allAtomMatchingTrackers,const unordered_map<int64_t,int> & conditionTrackerMap,const set<int64_t> & replacedConditions,vector<sp<ConditionTracker>> & allConditionTrackers,const vector<ConditionState> & initialConditionCache,const unordered_map<int64_t,int> & stateAtomIdMap,const unordered_map<int64_t,unordered_map<int,int64_t>> & allStateGroupMaps,const set<int64_t> & replacedStates,const unordered_map<int64_t,int> & oldMetricProducerMap,const vector<sp<MetricProducer>> & oldMetricProducers,const wp<ConfigMetadataProvider> configMetadataProvider,unordered_map<int64_t,int> & newMetricProducerMap,vector<sp<MetricProducer>> & newMetricProducers,unordered_map<int,vector<int>> & conditionToMetricMap,unordered_map<int,vector<int>> & trackerToMetricMap,set<int64_t> & noReportMetricIds,unordered_map<int,vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation,set<int64_t> & replacedMetrics)719 optional<InvalidConfigReason> updateMetrics(
720 const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
721 const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
722 const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
723 const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
724 const set<int64_t>& replacedMatchers,
725 const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
726 const unordered_map<int64_t, int>& conditionTrackerMap,
727 const set<int64_t>& replacedConditions, vector<sp<ConditionTracker>>& allConditionTrackers,
728 const vector<ConditionState>& initialConditionCache,
729 const unordered_map<int64_t, int>& stateAtomIdMap,
730 const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
731 const set<int64_t>& replacedStates, const unordered_map<int64_t, int>& oldMetricProducerMap,
732 const vector<sp<MetricProducer>>& oldMetricProducers,
733 const wp<ConfigMetadataProvider> configMetadataProvider,
734 unordered_map<int64_t, int>& newMetricProducerMap,
735 vector<sp<MetricProducer>>& newMetricProducers,
736 unordered_map<int, vector<int>>& conditionToMetricMap,
737 unordered_map<int, vector<int>>& trackerToMetricMap, set<int64_t>& noReportMetricIds,
738 unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
739 unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
740 vector<int>& metricsWithActivation, set<int64_t>& replacedMetrics) {
741 sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
742 sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchingTrackers);
743 const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
744 config.event_metric_size() + config.gauge_metric_size() +
745 config.value_metric_size() + config.kll_metric_size();
746 newMetricProducers.reserve(allMetricsCount);
747 optional<InvalidConfigReason> invalidConfigReason;
748
749 if (config.has_restricted_metrics_delegate_package_name() &&
750 allMetricsCount != config.event_metric_size()) {
751 ALOGE("Restricted metrics only support event metric");
752 return InvalidConfigReason(INVALID_CONFIG_REASON_RESTRICTED_METRIC_NOT_SUPPORTED);
753 }
754
755 // Construct map from metric id to metric activation index. The map will be used to determine
756 // the metric activation corresponding to a metric.
757 unordered_map<int64_t, int> metricToActivationMap;
758 for (int i = 0; i < config.metric_activation_size(); i++) {
759 const MetricActivation& metricActivation = config.metric_activation(i);
760 int64_t metricId = metricActivation.metric_id();
761 if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) {
762 ALOGE("Metric %lld has multiple MetricActivations", (long long)metricId);
763 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_HAS_MULTIPLE_ACTIVATIONS,
764 metricId);
765 }
766 metricToActivationMap.insert({metricId, i});
767 }
768
769 vector<UpdateStatus> metricsToUpdate(allMetricsCount, UPDATE_UNKNOWN);
770 invalidConfigReason = determineAllMetricUpdateStatuses(
771 config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
772 replacedMatchers, replacedConditions, replacedStates, metricsToUpdate);
773 if (invalidConfigReason.has_value()) {
774 return invalidConfigReason;
775 }
776
777 // Now, perform the update. Must iterate the metric types in the same order
778 int metricIndex = 0;
779 for (int i = 0; i < config.count_metric_size(); i++, metricIndex++) {
780 const CountMetric& metric = config.count_metric(i);
781 newMetricProducerMap[metric.id()] = metricIndex;
782 optional<sp<MetricProducer>> producer;
783 switch (metricsToUpdate[metricIndex]) {
784 case UPDATE_PRESERVE: {
785 producer = updateMetric(
786 config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
787 oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
788 allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
789 oldMetricProducers, metricToActivationMap, trackerToMetricMap,
790 conditionToMetricMap, activationAtomTrackerToMetricMap,
791 deactivationAtomTrackerToMetricMap, metricsWithActivation,
792 invalidConfigReason);
793 break;
794 }
795 case UPDATE_REPLACE:
796 replacedMetrics.insert(metric.id());
797 [[fallthrough]]; // Intentionally fallthrough to create the new metric producer.
798 case UPDATE_NEW: {
799 producer = createCountMetricProducerAndUpdateMetadata(
800 key, config, timeBaseNs, currentTimeNs, metric, metricIndex,
801 allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
802 conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
803 allStateGroupMaps, metricToActivationMap, trackerToMetricMap,
804 conditionToMetricMap, activationAtomTrackerToMetricMap,
805 deactivationAtomTrackerToMetricMap, metricsWithActivation,
806 invalidConfigReason, configMetadataProvider);
807 break;
808 }
809 default: {
810 ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
811 (long long)metric.id());
812 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
813 metric.id());
814 }
815 }
816 if (!producer) {
817 return invalidConfigReason;
818 }
819 newMetricProducers.push_back(producer.value());
820 }
821 for (int i = 0; i < config.duration_metric_size(); i++, metricIndex++) {
822 const DurationMetric& metric = config.duration_metric(i);
823 newMetricProducerMap[metric.id()] = metricIndex;
824 optional<sp<MetricProducer>> producer;
825 switch (metricsToUpdate[metricIndex]) {
826 case UPDATE_PRESERVE: {
827 producer = updateMetric(
828 config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
829 oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
830 allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
831 oldMetricProducers, metricToActivationMap, trackerToMetricMap,
832 conditionToMetricMap, activationAtomTrackerToMetricMap,
833 deactivationAtomTrackerToMetricMap, metricsWithActivation,
834 invalidConfigReason);
835 break;
836 }
837 case UPDATE_REPLACE:
838 replacedMetrics.insert(metric.id());
839 [[fallthrough]]; // Intentionally fallthrough to create the new metric producer.
840 case UPDATE_NEW: {
841 producer = createDurationMetricProducerAndUpdateMetadata(
842 key, config, timeBaseNs, currentTimeNs, metric, metricIndex,
843 allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
844 conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
845 allStateGroupMaps, metricToActivationMap, trackerToMetricMap,
846 conditionToMetricMap, activationAtomTrackerToMetricMap,
847 deactivationAtomTrackerToMetricMap, metricsWithActivation,
848 invalidConfigReason, configMetadataProvider);
849 break;
850 }
851 default: {
852 ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
853 (long long)metric.id());
854 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
855 metric.id());
856 }
857 }
858 if (!producer) {
859 return invalidConfigReason;
860 }
861 newMetricProducers.push_back(producer.value());
862 }
863 for (int i = 0; i < config.event_metric_size(); i++, metricIndex++) {
864 const EventMetric& metric = config.event_metric(i);
865 newMetricProducerMap[metric.id()] = metricIndex;
866 optional<sp<MetricProducer>> producer;
867 switch (metricsToUpdate[metricIndex]) {
868 case UPDATE_PRESERVE: {
869 producer = updateMetric(
870 config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
871 oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
872 allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
873 oldMetricProducers, metricToActivationMap, trackerToMetricMap,
874 conditionToMetricMap, activationAtomTrackerToMetricMap,
875 deactivationAtomTrackerToMetricMap, metricsWithActivation,
876 invalidConfigReason);
877 break;
878 }
879 case UPDATE_REPLACE:
880 replacedMetrics.insert(metric.id());
881 [[fallthrough]]; // Intentionally fallthrough to create the new metric producer.
882 case UPDATE_NEW: {
883 producer = createEventMetricProducerAndUpdateMetadata(
884 key, config, timeBaseNs, metric, metricIndex, allAtomMatchingTrackers,
885 newAtomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap,
886 initialConditionCache, wizard, metricToActivationMap, trackerToMetricMap,
887 conditionToMetricMap, activationAtomTrackerToMetricMap,
888 deactivationAtomTrackerToMetricMap, metricsWithActivation,
889 invalidConfigReason, configMetadataProvider);
890 break;
891 }
892 default: {
893 ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
894 (long long)metric.id());
895 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
896 metric.id());
897 }
898 }
899 if (!producer) {
900 return invalidConfigReason;
901 }
902 newMetricProducers.push_back(producer.value());
903 }
904
905 for (int i = 0; i < config.value_metric_size(); i++, metricIndex++) {
906 const ValueMetric& metric = config.value_metric(i);
907 newMetricProducerMap[metric.id()] = metricIndex;
908 optional<sp<MetricProducer>> producer;
909 switch (metricsToUpdate[metricIndex]) {
910 case UPDATE_PRESERVE: {
911 producer = updateMetric(
912 config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
913 oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
914 allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
915 oldMetricProducers, metricToActivationMap, trackerToMetricMap,
916 conditionToMetricMap, activationAtomTrackerToMetricMap,
917 deactivationAtomTrackerToMetricMap, metricsWithActivation,
918 invalidConfigReason);
919 break;
920 }
921 case UPDATE_REPLACE:
922 replacedMetrics.insert(metric.id());
923 [[fallthrough]]; // Intentionally fallthrough to create the new metric producer.
924 case UPDATE_NEW: {
925 producer = createNumericValueMetricProducerAndUpdateMetadata(
926 key, config, timeBaseNs, currentTimeNs, pullerManager, metric, metricIndex,
927 allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
928 conditionTrackerMap, initialConditionCache, wizard, matcherWizard,
929 stateAtomIdMap, allStateGroupMaps, metricToActivationMap,
930 trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
931 deactivationAtomTrackerToMetricMap, metricsWithActivation,
932 invalidConfigReason, configMetadataProvider);
933 break;
934 }
935 default: {
936 ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
937 (long long)metric.id());
938 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
939 metric.id());
940 }
941 }
942 if (!producer) {
943 return invalidConfigReason;
944 }
945 newMetricProducers.push_back(producer.value());
946 }
947
948 for (int i = 0; i < config.gauge_metric_size(); i++, metricIndex++) {
949 const GaugeMetric& metric = config.gauge_metric(i);
950 newMetricProducerMap[metric.id()] = metricIndex;
951 optional<sp<MetricProducer>> producer;
952 switch (metricsToUpdate[metricIndex]) {
953 case UPDATE_PRESERVE: {
954 producer = updateMetric(
955 config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
956 oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
957 allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
958 oldMetricProducers, metricToActivationMap, trackerToMetricMap,
959 conditionToMetricMap, activationAtomTrackerToMetricMap,
960 deactivationAtomTrackerToMetricMap, metricsWithActivation,
961 invalidConfigReason);
962 break;
963 }
964 case UPDATE_REPLACE:
965 replacedMetrics.insert(metric.id());
966 [[fallthrough]]; // Intentionally fallthrough to create the new metric producer.
967 case UPDATE_NEW: {
968 producer = createGaugeMetricProducerAndUpdateMetadata(
969 key, config, timeBaseNs, currentTimeNs, pullerManager, metric, metricIndex,
970 allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
971 conditionTrackerMap, initialConditionCache, wizard, matcherWizard,
972 metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
973 activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
974 metricsWithActivation, invalidConfigReason, configMetadataProvider);
975 break;
976 }
977 default: {
978 ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
979 (long long)metric.id());
980 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
981 metric.id());
982 }
983 }
984 if (!producer) {
985 return invalidConfigReason;
986 }
987 newMetricProducers.push_back(producer.value());
988 }
989
990 for (int i = 0; i < config.kll_metric_size(); i++, metricIndex++) {
991 const KllMetric& metric = config.kll_metric(i);
992 newMetricProducerMap[metric.id()] = metricIndex;
993 optional<sp<MetricProducer>> producer;
994 switch (metricsToUpdate[metricIndex]) {
995 case UPDATE_PRESERVE: {
996 producer = updateMetric(
997 config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
998 oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
999 allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
1000 oldMetricProducers, metricToActivationMap, trackerToMetricMap,
1001 conditionToMetricMap, activationAtomTrackerToMetricMap,
1002 deactivationAtomTrackerToMetricMap, metricsWithActivation,
1003 invalidConfigReason);
1004 break;
1005 }
1006 case UPDATE_REPLACE:
1007 replacedMetrics.insert(metric.id());
1008 [[fallthrough]]; // Intentionally fallthrough to create the new metric
1009 // producer.
1010 case UPDATE_NEW: {
1011 producer = createKllMetricProducerAndUpdateMetadata(
1012 key, config, timeBaseNs, currentTimeNs, pullerManager, metric, metricIndex,
1013 allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
1014 conditionTrackerMap, initialConditionCache, wizard, matcherWizard,
1015 stateAtomIdMap, allStateGroupMaps, metricToActivationMap,
1016 trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
1017 deactivationAtomTrackerToMetricMap, metricsWithActivation,
1018 invalidConfigReason, configMetadataProvider);
1019 break;
1020 }
1021 default: {
1022 ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
1023 (long long)metric.id());
1024 return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
1025 metric.id());
1026 }
1027 }
1028 if (!producer) {
1029 return invalidConfigReason;
1030 }
1031 newMetricProducers.push_back(producer.value());
1032 }
1033
1034 for (int i = 0; i < config.no_report_metric_size(); ++i) {
1035 const int64_t noReportMetric = config.no_report_metric(i);
1036 if (newMetricProducerMap.find(noReportMetric) == newMetricProducerMap.end()) {
1037 ALOGW("no_report_metric %" PRId64 " not exist", noReportMetric);
1038 return InvalidConfigReason(INVALID_CONFIG_REASON_NO_REPORT_METRIC_NOT_FOUND,
1039 noReportMetric);
1040 }
1041 noReportMetricIds.insert(noReportMetric);
1042 }
1043 const set<int> atomsAllowedFromAnyUid(config.whitelisted_atom_ids().begin(),
1044 config.whitelisted_atom_ids().end());
1045 for (int i = 0; i < allMetricsCount; i++) {
1046 sp<MetricProducer> producer = newMetricProducers[i];
1047 // Register metrics to StateTrackers
1048 for (int atomId : producer->getSlicedStateAtoms()) {
1049 // Register listener for atoms that use allowed_log_sources.
1050 // Using atoms allowed from any uid as a sliced state atom is not allowed.
1051 // Redo this check for all metrics in case the atoms allowed from any uid changed.
1052 if (atomsAllowedFromAnyUid.find(atomId) != atomsAllowedFromAnyUid.end()) {
1053 return InvalidConfigReason(
1054 INVALID_CONFIG_REASON_METRIC_SLICED_STATE_ATOM_ALLOWED_FROM_ANY_UID,
1055 producer->getMetricId());
1056 // Preserved metrics should've already registered.`
1057 } else if (metricsToUpdate[i] != UPDATE_PRESERVE) {
1058 StateManager::getInstance().registerListener(atomId, producer);
1059 }
1060 }
1061 }
1062
1063 // Init new/replaced metrics.
1064 for (size_t i = 0; i < newMetricProducers.size(); i++) {
1065 if (metricsToUpdate[i] == UPDATE_REPLACE || metricsToUpdate[i] == UPDATE_NEW) {
1066 newMetricProducers[i]->prepareFirstBucket();
1067 }
1068 }
1069
1070 for (const sp<MetricProducer>& oldMetricProducer : oldMetricProducers) {
1071 const auto& it = newMetricProducerMap.find(oldMetricProducer->getMetricId());
1072 // Consider metric removed if it's not present in newMetricProducerMap or it's replaced.
1073 if (it == newMetricProducerMap.end() ||
1074 replacedMetrics.find(oldMetricProducer->getMetricId()) != replacedMetrics.end()) {
1075 oldMetricProducer->onMetricRemove();
1076 }
1077 }
1078 return nullopt;
1079 }
1080
determineAlertUpdateStatus(const Alert & alert,const unordered_map<int64_t,int> & oldAlertTrackerMap,const vector<sp<AnomalyTracker>> & oldAnomalyTrackers,const set<int64_t> & replacedMetrics,UpdateStatus & updateStatus)1081 optional<InvalidConfigReason> determineAlertUpdateStatus(
1082 const Alert& alert, const unordered_map<int64_t, int>& oldAlertTrackerMap,
1083 const vector<sp<AnomalyTracker>>& oldAnomalyTrackers, const set<int64_t>& replacedMetrics,
1084 UpdateStatus& updateStatus) {
1085 // Check if new alert.
1086 const auto& oldAnomalyTrackerIt = oldAlertTrackerMap.find(alert.id());
1087 if (oldAnomalyTrackerIt == oldAlertTrackerMap.end()) {
1088 updateStatus = UPDATE_NEW;
1089 return nullopt;
1090 }
1091
1092 // This is an existing alert, check if it has changed.
1093 string serializedAlert;
1094 if (!alert.SerializeToString(&serializedAlert)) {
1095 ALOGW("Unable to serialize alert %lld", (long long)alert.id());
1096 return createInvalidConfigReasonWithAlert(INVALID_CONFIG_REASON_ALERT_SERIALIZATION_FAILED,
1097 alert.id());
1098 }
1099 uint64_t newProtoHash = Hash64(serializedAlert);
1100 const auto [invalidConfigReason, oldProtoHash] =
1101 oldAnomalyTrackers[oldAnomalyTrackerIt->second]->getProtoHash();
1102 if (invalidConfigReason.has_value()) {
1103 return invalidConfigReason;
1104 }
1105 if (newProtoHash != oldProtoHash) {
1106 updateStatus = UPDATE_REPLACE;
1107 return nullopt;
1108 }
1109
1110 // Check if the metric this alert relies on has changed.
1111 if (replacedMetrics.find(alert.metric_id()) != replacedMetrics.end()) {
1112 updateStatus = UPDATE_REPLACE;
1113 return nullopt;
1114 }
1115
1116 updateStatus = UPDATE_PRESERVE;
1117 return nullopt;
1118 }
1119
updateAlerts(const StatsdConfig & config,const int64_t currentTimeNs,const unordered_map<int64_t,int> & metricProducerMap,const set<int64_t> & replacedMetrics,const unordered_map<int64_t,int> & oldAlertTrackerMap,const vector<sp<AnomalyTracker>> & oldAnomalyTrackers,const sp<AlarmMonitor> & anomalyAlarmMonitor,vector<sp<MetricProducer>> & allMetricProducers,unordered_map<int64_t,int> & newAlertTrackerMap,vector<sp<AnomalyTracker>> & newAnomalyTrackers)1120 optional<InvalidConfigReason> updateAlerts(const StatsdConfig& config, const int64_t currentTimeNs,
1121 const unordered_map<int64_t, int>& metricProducerMap,
1122 const set<int64_t>& replacedMetrics,
1123 const unordered_map<int64_t, int>& oldAlertTrackerMap,
1124 const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
1125 const sp<AlarmMonitor>& anomalyAlarmMonitor,
1126 vector<sp<MetricProducer>>& allMetricProducers,
1127 unordered_map<int64_t, int>& newAlertTrackerMap,
1128 vector<sp<AnomalyTracker>>& newAnomalyTrackers) {
1129 int alertCount = config.alert_size();
1130 vector<UpdateStatus> alertUpdateStatuses(alertCount);
1131 optional<InvalidConfigReason> invalidConfigReason;
1132 for (int i = 0; i < alertCount; i++) {
1133 invalidConfigReason =
1134 determineAlertUpdateStatus(config.alert(i), oldAlertTrackerMap, oldAnomalyTrackers,
1135 replacedMetrics, alertUpdateStatuses[i]);
1136 if (invalidConfigReason.has_value()) {
1137 return invalidConfigReason;
1138 }
1139 }
1140
1141 for (int i = 0; i < alertCount; i++) {
1142 const Alert& alert = config.alert(i);
1143 newAlertTrackerMap[alert.id()] = newAnomalyTrackers.size();
1144 switch (alertUpdateStatuses[i]) {
1145 case UPDATE_PRESERVE: {
1146 // Find the alert and update it.
1147 const auto& oldAnomalyTrackerIt = oldAlertTrackerMap.find(alert.id());
1148 if (oldAnomalyTrackerIt == oldAlertTrackerMap.end()) {
1149 ALOGW("Could not find AnomalyTracker %lld in the previous config, but "
1150 "expected it to be there",
1151 (long long)alert.id());
1152 return createInvalidConfigReasonWithAlert(
1153 INVALID_CONFIG_REASON_ALERT_NOT_IN_PREV_CONFIG, alert.id());
1154 }
1155 sp<AnomalyTracker> anomalyTracker = oldAnomalyTrackers[oldAnomalyTrackerIt->second];
1156 anomalyTracker->onConfigUpdated();
1157 // Add the alert to the relevant metric.
1158 const auto& metricProducerIt = metricProducerMap.find(alert.metric_id());
1159 if (metricProducerIt == metricProducerMap.end()) {
1160 ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
1161 (long long)alert.metric_id());
1162 return createInvalidConfigReasonWithAlert(
1163 INVALID_CONFIG_REASON_ALERT_METRIC_NOT_FOUND, alert.metric_id(),
1164 alert.id());
1165 }
1166 allMetricProducers[metricProducerIt->second]->addAnomalyTracker(anomalyTracker,
1167 currentTimeNs);
1168 newAnomalyTrackers.push_back(anomalyTracker);
1169 break;
1170 }
1171 case UPDATE_REPLACE:
1172 case UPDATE_NEW: {
1173 optional<sp<AnomalyTracker>> anomalyTracker = createAnomalyTracker(
1174 alert, anomalyAlarmMonitor, alertUpdateStatuses[i], currentTimeNs,
1175 metricProducerMap, allMetricProducers, invalidConfigReason);
1176 if (!anomalyTracker) {
1177 return invalidConfigReason;
1178 }
1179 newAnomalyTrackers.push_back(anomalyTracker.value());
1180 break;
1181 }
1182 default: {
1183 ALOGE("Alert \"%lld\" update state is unknown. This should never happen",
1184 (long long)alert.id());
1185 return createInvalidConfigReasonWithAlert(
1186 INVALID_CONFIG_REASON_ALERT_UPDATE_STATUS_UNKNOWN, alert.id());
1187 }
1188 }
1189 }
1190 invalidConfigReason = initSubscribersForSubscriptionType(
1191 config, Subscription::ALERT, newAlertTrackerMap, newAnomalyTrackers);
1192 if (invalidConfigReason.has_value()) {
1193 return invalidConfigReason;
1194 }
1195 return nullopt;
1196 }
1197
updateStatsdConfig(const ConfigKey & key,const StatsdConfig & config,const sp<UidMap> & uidMap,const sp<StatsPullerManager> & pullerManager,const sp<AlarmMonitor> & anomalyAlarmMonitor,const sp<AlarmMonitor> & periodicAlarmMonitor,const int64_t timeBaseNs,const int64_t currentTimeNs,const vector<sp<AtomMatchingTracker>> & oldAtomMatchingTrackers,const unordered_map<int64_t,int> & oldAtomMatchingTrackerMap,const vector<sp<ConditionTracker>> & oldConditionTrackers,const unordered_map<int64_t,int> & oldConditionTrackerMap,const vector<sp<MetricProducer>> & oldMetricProducers,const unordered_map<int64_t,int> & oldMetricProducerMap,const vector<sp<AnomalyTracker>> & oldAnomalyTrackers,const unordered_map<int64_t,int> & oldAlertTrackerMap,const map<int64_t,uint64_t> & oldStateProtoHashes,const wp<ConfigMetadataProvider> configMetadataProvider,std::unordered_map<int,std::vector<int>> & allTagIdsToMatchersMap,vector<sp<AtomMatchingTracker>> & newAtomMatchingTrackers,unordered_map<int64_t,int> & newAtomMatchingTrackerMap,vector<sp<ConditionTracker>> & newConditionTrackers,unordered_map<int64_t,int> & newConditionTrackerMap,vector<sp<MetricProducer>> & newMetricProducers,unordered_map<int64_t,int> & newMetricProducerMap,vector<sp<AnomalyTracker>> & newAnomalyTrackers,unordered_map<int64_t,int> & newAlertTrackerMap,vector<sp<AlarmTracker>> & newPeriodicAlarmTrackers,unordered_map<int,vector<int>> & conditionToMetricMap,unordered_map<int,vector<int>> & trackerToMetricMap,unordered_map<int,vector<int>> & trackerToConditionMap,unordered_map<int,vector<int>> & activationTrackerToMetricMap,unordered_map<int,vector<int>> & deactivationTrackerToMetricMap,vector<int> & metricsWithActivation,map<int64_t,uint64_t> & newStateProtoHashes,set<int64_t> & noReportMetricIds)1198 optional<InvalidConfigReason> updateStatsdConfig(
1199 const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
1200 const sp<StatsPullerManager>& pullerManager, const sp<AlarmMonitor>& anomalyAlarmMonitor,
1201 const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
1202 const int64_t currentTimeNs, const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
1203 const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
1204 const vector<sp<ConditionTracker>>& oldConditionTrackers,
1205 const unordered_map<int64_t, int>& oldConditionTrackerMap,
1206 const vector<sp<MetricProducer>>& oldMetricProducers,
1207 const unordered_map<int64_t, int>& oldMetricProducerMap,
1208 const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
1209 const unordered_map<int64_t, int>& oldAlertTrackerMap,
1210 const map<int64_t, uint64_t>& oldStateProtoHashes,
1211 const wp<ConfigMetadataProvider> configMetadataProvider,
1212 std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
1213 vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
1214 unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
1215 vector<sp<ConditionTracker>>& newConditionTrackers,
1216 unordered_map<int64_t, int>& newConditionTrackerMap,
1217 vector<sp<MetricProducer>>& newMetricProducers,
1218 unordered_map<int64_t, int>& newMetricProducerMap,
1219 vector<sp<AnomalyTracker>>& newAnomalyTrackers,
1220 unordered_map<int64_t, int>& newAlertTrackerMap,
1221 vector<sp<AlarmTracker>>& newPeriodicAlarmTrackers,
1222 unordered_map<int, vector<int>>& conditionToMetricMap,
1223 unordered_map<int, vector<int>>& trackerToMetricMap,
1224 unordered_map<int, vector<int>>& trackerToConditionMap,
1225 unordered_map<int, vector<int>>& activationTrackerToMetricMap,
1226 unordered_map<int, vector<int>>& deactivationTrackerToMetricMap,
1227 vector<int>& metricsWithActivation, map<int64_t, uint64_t>& newStateProtoHashes,
1228 set<int64_t>& noReportMetricIds) {
1229 set<int64_t> replacedMatchers;
1230 set<int64_t> replacedConditions;
1231 set<int64_t> replacedStates;
1232 set<int64_t> replacedMetrics;
1233 vector<ConditionState> conditionCache;
1234 unordered_map<int64_t, int> stateAtomIdMap;
1235 unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
1236
1237 if (config.package_certificate_hash_size_bytes() > UINT8_MAX) {
1238 ALOGE("Invalid value for package_certificate_hash_size_bytes: %d",
1239 config.package_certificate_hash_size_bytes());
1240 return InvalidConfigReason(INVALID_CONFIG_REASON_PACKAGE_CERT_HASH_SIZE_TOO_LARGE);
1241 }
1242
1243 optional<InvalidConfigReason> invalidConfigReason = updateAtomMatchingTrackers(
1244 config, uidMap, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers,
1245 allTagIdsToMatchersMap, newAtomMatchingTrackerMap, newAtomMatchingTrackers,
1246 replacedMatchers);
1247 if (invalidConfigReason.has_value()) {
1248 ALOGE("updateAtomMatchingTrackers failed");
1249 return invalidConfigReason;
1250 }
1251
1252 invalidConfigReason = updateConditions(
1253 key, config, newAtomMatchingTrackerMap, replacedMatchers, oldConditionTrackerMap,
1254 oldConditionTrackers, newConditionTrackerMap, newConditionTrackers,
1255 trackerToConditionMap, conditionCache, replacedConditions);
1256 if (invalidConfigReason.has_value()) {
1257 ALOGE("updateConditions failed");
1258 return invalidConfigReason;
1259 }
1260
1261 invalidConfigReason = updateStates(config, oldStateProtoHashes, stateAtomIdMap,
1262 allStateGroupMaps, newStateProtoHashes, replacedStates);
1263 if (invalidConfigReason.has_value()) {
1264 ALOGE("updateStates failed");
1265 return invalidConfigReason;
1266 }
1267
1268 invalidConfigReason = updateMetrics(
1269 key, config, timeBaseNs, currentTimeNs, pullerManager, oldAtomMatchingTrackerMap,
1270 newAtomMatchingTrackerMap, replacedMatchers, newAtomMatchingTrackers,
1271 newConditionTrackerMap, replacedConditions, newConditionTrackers, conditionCache,
1272 stateAtomIdMap, allStateGroupMaps, replacedStates, oldMetricProducerMap,
1273 oldMetricProducers, configMetadataProvider, newMetricProducerMap, newMetricProducers,
1274 conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
1275 activationTrackerToMetricMap, deactivationTrackerToMetricMap, metricsWithActivation,
1276 replacedMetrics);
1277 if (invalidConfigReason.has_value()) {
1278 ALOGE("updateMetrics failed");
1279 return invalidConfigReason;
1280 }
1281
1282 invalidConfigReason = updateAlerts(config, currentTimeNs, newMetricProducerMap, replacedMetrics,
1283 oldAlertTrackerMap, oldAnomalyTrackers, anomalyAlarmMonitor,
1284 newMetricProducers, newAlertTrackerMap, newAnomalyTrackers);
1285 if (invalidConfigReason.has_value()) {
1286 ALOGE("updateAlerts failed");
1287 return invalidConfigReason;
1288 }
1289
1290 invalidConfigReason = initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
1291 newPeriodicAlarmTrackers);
1292 // Alarms do not have any state, so we can reuse the initialization logic.
1293 if (invalidConfigReason.has_value()) {
1294 ALOGE("initAlarms failed");
1295 return invalidConfigReason;
1296 }
1297 return nullopt;
1298 }
1299
1300 } // namespace statsd
1301 } // namespace os
1302 } // namespace android
1303