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