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