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