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