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