1 /*
2  * Copyright (C) 2017 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 "metrics_manager_util.h"
21 
22 #include "../condition/CombinationConditionTracker.h"
23 #include "../condition/SimpleConditionTracker.h"
24 #include "../condition/StateTracker.h"
25 #include "../external/StatsPullerManager.h"
26 #include "../matchers/CombinationLogMatchingTracker.h"
27 #include "../matchers/SimpleLogMatchingTracker.h"
28 #include "../matchers/EventMatcherWizard.h"
29 #include "../metrics/CountMetricProducer.h"
30 #include "../metrics/DurationMetricProducer.h"
31 #include "../metrics/EventMetricProducer.h"
32 #include "../metrics/GaugeMetricProducer.h"
33 #include "../metrics/ValueMetricProducer.h"
34 
35 #include "stats_util.h"
36 #include "statslog.h"
37 
38 using std::set;
39 using std::string;
40 using std::unordered_map;
41 using std::vector;
42 
43 namespace android {
44 namespace os {
45 namespace statsd {
46 
47 namespace {
48 
hasLeafNode(const FieldMatcher & matcher)49 bool hasLeafNode(const FieldMatcher& matcher) {
50     if (!matcher.has_field()) {
51         return false;
52     }
53     for (int i = 0; i < matcher.child_size(); ++i) {
54         if (hasLeafNode(matcher.child(i))) {
55             return true;
56         }
57     }
58     return true;
59 }
60 
61 }  // namespace
62 
handleMetricWithLogTrackers(const int64_t what,const int metricIndex,const bool usedForDimension,const vector<sp<LogMatchingTracker>> & allAtomMatchers,const unordered_map<int64_t,int> & logTrackerMap,unordered_map<int,std::vector<int>> & trackerToMetricMap,int & logTrackerIndex)63 bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex,
64                                  const bool usedForDimension,
65                                  const vector<sp<LogMatchingTracker>>& allAtomMatchers,
66                                  const unordered_map<int64_t, int>& logTrackerMap,
67                                  unordered_map<int, std::vector<int>>& trackerToMetricMap,
68                                  int& logTrackerIndex) {
69     auto logTrackerIt = logTrackerMap.find(what);
70     if (logTrackerIt == logTrackerMap.end()) {
71         ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)what);
72         return false;
73     }
74     if (usedForDimension && allAtomMatchers[logTrackerIt->second]->getAtomIds().size() > 1) {
75         ALOGE("AtomMatcher \"%lld\" has more than one tag ids. When a metric has dimension, "
76               "the \"what\" can only about one atom type.",
77               (long long)what);
78         return false;
79     }
80     logTrackerIndex = logTrackerIt->second;
81     auto& metric_list = trackerToMetricMap[logTrackerIndex];
82     metric_list.push_back(metricIndex);
83     return true;
84 }
85 
handlePullMetricTriggerWithLogTrackers(const int64_t trigger,const int metricIndex,const vector<sp<LogMatchingTracker>> & allAtomMatchers,const unordered_map<int64_t,int> & logTrackerMap,unordered_map<int,std::vector<int>> & trackerToMetricMap,int & logTrackerIndex)86 bool handlePullMetricTriggerWithLogTrackers(
87         const int64_t trigger, const int metricIndex,
88         const vector<sp<LogMatchingTracker>>& allAtomMatchers,
89         const unordered_map<int64_t, int>& logTrackerMap,
90         unordered_map<int, std::vector<int>>& trackerToMetricMap, int& logTrackerIndex) {
91     auto logTrackerIt = logTrackerMap.find(trigger);
92     if (logTrackerIt == logTrackerMap.end()) {
93         ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)trigger);
94         return false;
95     }
96     if (allAtomMatchers[logTrackerIt->second]->getAtomIds().size() > 1) {
97         ALOGE("AtomMatcher \"%lld\" has more than one tag ids."
98               "Trigger can only be one atom type.",
99               (long long)trigger);
100         return false;
101     }
102     logTrackerIndex = logTrackerIt->second;
103     auto& metric_list = trackerToMetricMap[logTrackerIndex];
104     metric_list.push_back(metricIndex);
105     return true;
106 }
107 
handleMetricWithConditions(const int64_t condition,const int metricIndex,const unordered_map<int64_t,int> & conditionTrackerMap,const::google::protobuf::RepeatedPtrField<::android::os::statsd::MetricConditionLink> & links,vector<sp<ConditionTracker>> & allConditionTrackers,int & conditionIndex,unordered_map<int,std::vector<int>> & conditionToMetricMap)108 bool handleMetricWithConditions(
109         const int64_t condition, const int metricIndex,
110         const unordered_map<int64_t, int>& conditionTrackerMap,
111         const ::google::protobuf::RepeatedPtrField<::android::os::statsd::MetricConditionLink>&
112                 links,
113         vector<sp<ConditionTracker>>& allConditionTrackers, int& conditionIndex,
114         unordered_map<int, std::vector<int>>& conditionToMetricMap) {
115     auto condition_it = conditionTrackerMap.find(condition);
116     if (condition_it == conditionTrackerMap.end()) {
117         ALOGW("cannot find Predicate \"%lld\" in the config", (long long)condition);
118         return false;
119     }
120 
121     for (const auto& link : links) {
122         auto it = conditionTrackerMap.find(link.condition());
123         if (it == conditionTrackerMap.end()) {
124             ALOGW("cannot find Predicate \"%lld\" in the config", (long long)link.condition());
125             return false;
126         }
127         allConditionTrackers[condition_it->second]->setSliced(true);
128         allConditionTrackers[it->second]->setSliced(true);
129     }
130     conditionIndex = condition_it->second;
131 
132     // will create new vector if not exist before.
133     auto& metricList = conditionToMetricMap[condition_it->second];
134     metricList.push_back(metricIndex);
135     return true;
136 }
137 
initLogTrackers(const StatsdConfig & config,const UidMap & uidMap,unordered_map<int64_t,int> & logTrackerMap,vector<sp<LogMatchingTracker>> & allAtomMatchers,set<int> & allTagIds)138 bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
139                      unordered_map<int64_t, int>& logTrackerMap,
140                      vector<sp<LogMatchingTracker>>& allAtomMatchers, set<int>& allTagIds) {
141     vector<AtomMatcher> matcherConfigs;
142     const int atomMatcherCount = config.atom_matcher_size();
143     matcherConfigs.reserve(atomMatcherCount);
144     allAtomMatchers.reserve(atomMatcherCount);
145 
146     for (int i = 0; i < atomMatcherCount; i++) {
147         const AtomMatcher& logMatcher = config.atom_matcher(i);
148 
149         int index = allAtomMatchers.size();
150         switch (logMatcher.contents_case()) {
151             case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
152                 allAtomMatchers.push_back(new SimpleLogMatchingTracker(
153                         logMatcher.id(), index, logMatcher.simple_atom_matcher(), uidMap));
154                 break;
155             case AtomMatcher::ContentsCase::kCombination:
156                 allAtomMatchers.push_back(
157                         new CombinationLogMatchingTracker(logMatcher.id(), index));
158                 break;
159             default:
160                 ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
161                 return false;
162                 // continue;
163         }
164         if (logTrackerMap.find(logMatcher.id()) != logTrackerMap.end()) {
165             ALOGE("Duplicate AtomMatcher found!");
166             return false;
167         }
168         logTrackerMap[logMatcher.id()] = index;
169         matcherConfigs.push_back(logMatcher);
170     }
171 
172     vector<bool> stackTracker2(allAtomMatchers.size(), false);
173     for (auto& matcher : allAtomMatchers) {
174         if (!matcher->init(matcherConfigs, allAtomMatchers, logTrackerMap, stackTracker2)) {
175             return false;
176         }
177         // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
178         const set<int>& tagIds = matcher->getAtomIds();
179         allTagIds.insert(tagIds.begin(), tagIds.end());
180     }
181     return true;
182 }
183 
184 /**
185  * A StateTracker is built from a SimplePredicate which has only "start", and no "stop"
186  * or "stop_all". The start must be an atom matcher that matches a state atom. It must
187  * have dimension, the dimension must be the state atom's primary fields plus exclusive state
188  * field. For example, the StateTracker is used in tracking UidProcessState and ScreenState.
189  *
190  */
isStateTracker(const SimplePredicate & simplePredicate,vector<Matcher> * primaryKeys)191 bool isStateTracker(const SimplePredicate& simplePredicate, vector<Matcher>* primaryKeys) {
192     // 1. must not have "stop". must have "dimension"
193     if (!simplePredicate.has_stop() && simplePredicate.has_dimensions()) {
194         auto it = android::util::AtomsInfo::kStateAtomsFieldOptions.find(
195                 simplePredicate.dimensions().field());
196         // 2. must be based on a state atom.
197         if (it != android::util::AtomsInfo::kStateAtomsFieldOptions.end()) {
198             // 3. dimension must be primary fields + state field IN ORDER
199             size_t expectedDimensionCount = it->second.primaryFields.size() + 1;
200             vector<Matcher> dimensions;
201             translateFieldMatcher(simplePredicate.dimensions(), &dimensions);
202             if (dimensions.size() != expectedDimensionCount) {
203                 return false;
204             }
205             // 3.1 check the primary fields first.
206             size_t index = 0;
207             for (const auto& field : it->second.primaryFields) {
208                 Matcher matcher = getSimpleMatcher(it->first, field);
209                 if (!(matcher == dimensions[index])) {
210                     return false;
211                 }
212                 primaryKeys->push_back(matcher);
213                 index++;
214             }
215             Matcher stateFieldMatcher =
216                     getSimpleMatcher(it->first, it->second.exclusiveField);
217             // 3.2 last dimension should be the exclusive field.
218             if (!(dimensions.back() == stateFieldMatcher)) {
219                 return false;
220             }
221             return true;
222         }
223     }
224     return false;
225 }  // namespace statsd
226 
initConditions(const ConfigKey & key,const StatsdConfig & config,const unordered_map<int64_t,int> & logTrackerMap,unordered_map<int64_t,int> & conditionTrackerMap,vector<sp<ConditionTracker>> & allConditionTrackers,unordered_map<int,std::vector<int>> & trackerToConditionMap)227 bool initConditions(const ConfigKey& key, const StatsdConfig& config,
228                     const unordered_map<int64_t, int>& logTrackerMap,
229                     unordered_map<int64_t, int>& conditionTrackerMap,
230                     vector<sp<ConditionTracker>>& allConditionTrackers,
231                     unordered_map<int, std::vector<int>>& trackerToConditionMap) {
232     vector<Predicate> conditionConfigs;
233     const int conditionTrackerCount = config.predicate_size();
234     conditionConfigs.reserve(conditionTrackerCount);
235     allConditionTrackers.reserve(conditionTrackerCount);
236 
237     for (int i = 0; i < conditionTrackerCount; i++) {
238         const Predicate& condition = config.predicate(i);
239         int index = allConditionTrackers.size();
240         switch (condition.contents_case()) {
241             case Predicate::ContentsCase::kSimplePredicate: {
242                 vector<Matcher> primaryKeys;
243                 if (isStateTracker(condition.simple_predicate(), &primaryKeys)) {
244                     allConditionTrackers.push_back(new StateTracker(key, condition.id(), index,
245                                                                     condition.simple_predicate(),
246                                                                     logTrackerMap, primaryKeys));
247                 } else {
248                     allConditionTrackers.push_back(new SimpleConditionTracker(
249                             key, condition.id(), index, condition.simple_predicate(),
250                             logTrackerMap));
251                 }
252                 break;
253             }
254             case Predicate::ContentsCase::kCombination: {
255                 allConditionTrackers.push_back(
256                         new CombinationConditionTracker(condition.id(), index));
257                 break;
258             }
259             default:
260                 ALOGE("Predicate \"%lld\" malformed", (long long)condition.id());
261                 return false;
262         }
263         if (conditionTrackerMap.find(condition.id()) != conditionTrackerMap.end()) {
264             ALOGE("Duplicate Predicate found!");
265             return false;
266         }
267         conditionTrackerMap[condition.id()] = index;
268         conditionConfigs.push_back(condition);
269     }
270 
271     vector<bool> stackTracker(allConditionTrackers.size(), false);
272     for (size_t i = 0; i < allConditionTrackers.size(); i++) {
273         auto& conditionTracker = allConditionTrackers[i];
274         if (!conditionTracker->init(conditionConfigs, allConditionTrackers, conditionTrackerMap,
275                                     stackTracker)) {
276             return false;
277         }
278         for (const int trackerIndex : conditionTracker->getLogTrackerIndex()) {
279             auto& conditionList = trackerToConditionMap[trackerIndex];
280             conditionList.push_back(i);
281         }
282     }
283     return true;
284 }
285 
initMetrics(const ConfigKey & key,const StatsdConfig & config,const int64_t timeBaseTimeNs,const int64_t currentTimeNs,UidMap & uidMap,const sp<StatsPullerManager> & pullerManager,const unordered_map<int64_t,int> & logTrackerMap,const unordered_map<int64_t,int> & conditionTrackerMap,const vector<sp<LogMatchingTracker>> & allAtomMatchers,vector<sp<ConditionTracker>> & allConditionTrackers,vector<sp<MetricProducer>> & allMetricProducers,unordered_map<int,std::vector<int>> & conditionToMetricMap,unordered_map<int,std::vector<int>> & trackerToMetricMap,unordered_map<int64_t,int> & metricMap,std::set<int64_t> & noReportMetricIds)286 bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
287                  const int64_t currentTimeNs, UidMap& uidMap,
288                  const sp<StatsPullerManager>& pullerManager,
289                  const unordered_map<int64_t, int>& logTrackerMap,
290                  const unordered_map<int64_t, int>& conditionTrackerMap,
291                  const vector<sp<LogMatchingTracker>>& allAtomMatchers,
292                  vector<sp<ConditionTracker>>& allConditionTrackers,
293                  vector<sp<MetricProducer>>& allMetricProducers,
294                  unordered_map<int, std::vector<int>>& conditionToMetricMap,
295                  unordered_map<int, std::vector<int>>& trackerToMetricMap,
296                  unordered_map<int64_t, int>& metricMap, std::set<int64_t>& noReportMetricIds) {
297     sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
298     sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchers);
299     const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
300                                 config.event_metric_size() + config.value_metric_size();
301     allMetricProducers.reserve(allMetricsCount);
302     StatsPullerManager statsPullerManager;
303 
304     // Build MetricProducers for each metric defined in config.
305     // build CountMetricProducer
306     for (int i = 0; i < config.count_metric_size(); i++) {
307         const CountMetric& metric = config.count_metric(i);
308         if (!metric.has_what()) {
309             ALOGW("cannot find \"what\" in CountMetric \"%lld\"", (long long)metric.id());
310             return false;
311         }
312 
313         int metricIndex = allMetricProducers.size();
314         metricMap.insert({metric.id(), metricIndex});
315         int trackerIndex;
316         if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
317                                          metric.has_dimensions_in_what(),
318                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
319                                          trackerIndex)) {
320             return false;
321         }
322 
323         int conditionIndex = -1;
324         if (metric.has_condition()) {
325             bool good = handleMetricWithConditions(
326                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
327                     allConditionTrackers, conditionIndex, conditionToMetricMap);
328             if (!good) {
329                 return false;
330             }
331         } else {
332             if (metric.links_size() > 0) {
333                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
334                 return false;
335             }
336         }
337 
338         sp<MetricProducer> countProducer =
339                 new CountMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs, currentTimeNs);
340         allMetricProducers.push_back(countProducer);
341     }
342 
343     // build DurationMetricProducer
344     for (int i = 0; i < config.duration_metric_size(); i++) {
345         int metricIndex = allMetricProducers.size();
346         const DurationMetric& metric = config.duration_metric(i);
347         metricMap.insert({metric.id(), metricIndex});
348 
349         auto what_it = conditionTrackerMap.find(metric.what());
350         if (what_it == conditionTrackerMap.end()) {
351             ALOGE("DurationMetric's \"what\" is invalid");
352             return false;
353         }
354 
355         const Predicate& durationWhat = config.predicate(what_it->second);
356 
357         if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
358             ALOGE("DurationMetric's \"what\" must be a simple condition");
359             return false;
360         }
361 
362         const auto& simplePredicate = durationWhat.simple_predicate();
363 
364         bool nesting = simplePredicate.count_nesting();
365 
366         int trackerIndices[3] = {-1, -1, -1};
367         if (!simplePredicate.has_start() ||
368             !handleMetricWithLogTrackers(simplePredicate.start(), metricIndex,
369                                          metric.has_dimensions_in_what(), allAtomMatchers,
370                                          logTrackerMap, trackerToMetricMap, trackerIndices[0])) {
371             ALOGE("Duration metrics must specify a valid the start event matcher");
372             return false;
373         }
374 
375         if (simplePredicate.has_stop() &&
376             !handleMetricWithLogTrackers(simplePredicate.stop(), metricIndex,
377                                          metric.has_dimensions_in_what(), allAtomMatchers,
378                                          logTrackerMap, trackerToMetricMap, trackerIndices[1])) {
379             return false;
380         }
381 
382         if (simplePredicate.has_stop_all() &&
383             !handleMetricWithLogTrackers(simplePredicate.stop_all(), metricIndex,
384                                          metric.has_dimensions_in_what(), allAtomMatchers,
385                                          logTrackerMap, trackerToMetricMap, trackerIndices[2])) {
386             return false;
387         }
388 
389         FieldMatcher internalDimensions = simplePredicate.dimensions();
390 
391         int conditionIndex = -1;
392 
393         if (metric.has_condition()) {
394             bool good = handleMetricWithConditions(
395                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
396                     allConditionTrackers, conditionIndex, conditionToMetricMap);
397             if (!good) {
398                 return false;
399             }
400         } else {
401             if (metric.links_size() > 0) {
402                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
403                 return false;
404             }
405         }
406 
407         sp<MetricProducer> durationMetric = new DurationMetricProducer(
408                 key, metric, conditionIndex, trackerIndices[0], trackerIndices[1],
409                 trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs, currentTimeNs);
410 
411         allMetricProducers.push_back(durationMetric);
412     }
413 
414     // build EventMetricProducer
415     for (int i = 0; i < config.event_metric_size(); i++) {
416         int metricIndex = allMetricProducers.size();
417         const EventMetric& metric = config.event_metric(i);
418         metricMap.insert({metric.id(), metricIndex});
419         if (!metric.has_id() || !metric.has_what()) {
420             ALOGW("cannot find the metric name or what in config");
421             return false;
422         }
423         int trackerIndex;
424         if (!handleMetricWithLogTrackers(metric.what(), metricIndex, false, allAtomMatchers,
425                                          logTrackerMap, trackerToMetricMap, trackerIndex)) {
426             return false;
427         }
428 
429         int conditionIndex = -1;
430         if (metric.has_condition()) {
431             bool good = handleMetricWithConditions(
432                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
433                     allConditionTrackers, conditionIndex, conditionToMetricMap);
434             if (!good) {
435                 return false;
436             }
437         } else {
438             if (metric.links_size() > 0) {
439                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
440                 return false;
441             }
442         }
443 
444         sp<MetricProducer> eventMetric =
445                 new EventMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
446 
447         allMetricProducers.push_back(eventMetric);
448     }
449 
450     // build ValueMetricProducer
451     for (int i = 0; i < config.value_metric_size(); i++) {
452         const ValueMetric& metric = config.value_metric(i);
453         if (!metric.has_what()) {
454             ALOGW("cannot find \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
455             return false;
456         }
457         if (!metric.has_value_field()) {
458             ALOGW("cannot find \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
459             return false;
460         }
461         std::vector<Matcher> fieldMatchers;
462         translateFieldMatcher(metric.value_field(), &fieldMatchers);
463         if (fieldMatchers.size() < 1) {
464             ALOGW("incorrect \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
465             return false;
466         }
467 
468         int metricIndex = allMetricProducers.size();
469         metricMap.insert({metric.id(), metricIndex});
470         int trackerIndex;
471         if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
472                                          metric.has_dimensions_in_what(),
473                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
474                                          trackerIndex)) {
475             return false;
476         }
477 
478         sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex);
479         // If it is pulled atom, it should be simple matcher with one tagId.
480         if (atomMatcher->getAtomIds().size() != 1) {
481             return false;
482         }
483         int atomTagId = *(atomMatcher->getAtomIds().begin());
484         int pullTagId = statsPullerManager.PullerForMatcherExists(atomTagId) ? atomTagId : -1;
485 
486         int conditionIndex = -1;
487         if (metric.has_condition()) {
488             bool good = handleMetricWithConditions(
489                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
490                     allConditionTrackers, conditionIndex, conditionToMetricMap);
491             if (!good) {
492                 return false;
493             }
494         } else {
495             if (metric.links_size() > 0) {
496                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
497                 return false;
498             }
499         }
500 
501         sp<MetricProducer> valueProducer = new ValueMetricProducer(
502                 key, metric, conditionIndex, wizard, trackerIndex, matcherWizard, pullTagId,
503                 timeBaseTimeNs, currentTimeNs, pullerManager);
504         allMetricProducers.push_back(valueProducer);
505     }
506 
507     // Gauge metrics.
508     for (int i = 0; i < config.gauge_metric_size(); i++) {
509         const GaugeMetric& metric = config.gauge_metric(i);
510         if (!metric.has_what()) {
511             ALOGW("cannot find \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
512             return false;
513         }
514 
515         if ((!metric.gauge_fields_filter().has_include_all() ||
516              (metric.gauge_fields_filter().include_all() == false)) &&
517             !hasLeafNode(metric.gauge_fields_filter().fields())) {
518             ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
519             return false;
520         }
521         if ((metric.gauge_fields_filter().has_include_all() &&
522              metric.gauge_fields_filter().include_all() == true) &&
523             hasLeafNode(metric.gauge_fields_filter().fields())) {
524             ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
525             return false;
526         }
527 
528         int metricIndex = allMetricProducers.size();
529         metricMap.insert({metric.id(), metricIndex});
530         int trackerIndex;
531         if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
532                                          metric.has_dimensions_in_what(),
533                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
534                                          trackerIndex)) {
535             return false;
536         }
537 
538         sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex);
539         // For GaugeMetric atom, it should be simple matcher with one tagId.
540         if (atomMatcher->getAtomIds().size() != 1) {
541             return false;
542         }
543         int atomTagId = *(atomMatcher->getAtomIds().begin());
544         int pullTagId = statsPullerManager.PullerForMatcherExists(atomTagId) ? atomTagId : -1;
545 
546         int triggerTrackerIndex;
547         int triggerAtomId = -1;
548         if (metric.has_trigger_event()) {
549             if (pullTagId == -1) {
550                 ALOGW("Pull atom not specified for trigger");
551                 return false;
552             }
553             // event_trigger should be used with FIRST_N_SAMPLES
554             if (metric.sampling_type() != GaugeMetric::FIRST_N_SAMPLES) {
555                 return false;
556             }
557             if (!handlePullMetricTriggerWithLogTrackers(metric.trigger_event(), metricIndex,
558                                                         allAtomMatchers, logTrackerMap,
559                                                         trackerToMetricMap, triggerTrackerIndex)) {
560                 return false;
561             }
562             sp<LogMatchingTracker> triggerAtomMatcher = allAtomMatchers.at(triggerTrackerIndex);
563             triggerAtomId = *(triggerAtomMatcher->getAtomIds().begin());
564         }
565 
566         if (!metric.has_trigger_event() && pullTagId != -1 &&
567             metric.sampling_type() == GaugeMetric::FIRST_N_SAMPLES) {
568             ALOGW("FIRST_N_SAMPLES is only for pushed event or pull_on_trigger");
569             return false;
570         }
571 
572         int conditionIndex = -1;
573         if (metric.has_condition()) {
574             bool good = handleMetricWithConditions(
575                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
576                     allConditionTrackers, conditionIndex, conditionToMetricMap);
577             if (!good) {
578                 return false;
579             }
580         } else {
581             if (metric.links_size() > 0) {
582                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
583                 return false;
584             }
585         }
586 
587         sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
588                 key, metric, conditionIndex, wizard,
589                 trackerIndex, matcherWizard, pullTagId, triggerAtomId, atomTagId,
590                 timeBaseTimeNs, currentTimeNs, pullerManager);
591         allMetricProducers.push_back(gaugeProducer);
592     }
593     for (int i = 0; i < config.no_report_metric_size(); ++i) {
594         const auto no_report_metric = config.no_report_metric(i);
595         if (metricMap.find(no_report_metric) == metricMap.end()) {
596             ALOGW("no_report_metric %lld not exist", no_report_metric);
597             return false;
598         }
599         noReportMetricIds.insert(no_report_metric);
600     }
601     for (const auto& it : allMetricProducers) {
602         uidMap.addListener(it);
603     }
604     return true;
605 }
606 
initAlerts(const StatsdConfig & config,const unordered_map<int64_t,int> & metricProducerMap,const sp<AlarmMonitor> & anomalyAlarmMonitor,vector<sp<MetricProducer>> & allMetricProducers,vector<sp<AnomalyTracker>> & allAnomalyTrackers)607 bool initAlerts(const StatsdConfig& config,
608                 const unordered_map<int64_t, int>& metricProducerMap,
609                 const sp<AlarmMonitor>& anomalyAlarmMonitor,
610                 vector<sp<MetricProducer>>& allMetricProducers,
611                 vector<sp<AnomalyTracker>>& allAnomalyTrackers) {
612     unordered_map<int64_t, int> anomalyTrackerMap;
613     for (int i = 0; i < config.alert_size(); i++) {
614         const Alert& alert = config.alert(i);
615         const auto& itr = metricProducerMap.find(alert.metric_id());
616         if (itr == metricProducerMap.end()) {
617             ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
618                   (long long)alert.metric_id());
619             return false;
620         }
621         if (!alert.has_trigger_if_sum_gt()) {
622             ALOGW("invalid alert: missing threshold");
623             return false;
624         }
625         if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
626             ALOGW("invalid alert: threshold=%f num_buckets= %d",
627                   alert.trigger_if_sum_gt(), alert.num_buckets());
628             return false;
629         }
630         const int metricIndex = itr->second;
631         sp<MetricProducer> metric = allMetricProducers[metricIndex];
632         sp<AnomalyTracker> anomalyTracker = metric->addAnomalyTracker(alert, anomalyAlarmMonitor);
633         if (anomalyTracker == nullptr) {
634             // The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
635             return false;
636         }
637         anomalyTrackerMap.insert(std::make_pair(alert.id(), allAnomalyTrackers.size()));
638         allAnomalyTrackers.push_back(anomalyTracker);
639     }
640     for (int i = 0; i < config.subscription_size(); ++i) {
641         const Subscription& subscription = config.subscription(i);
642         if (subscription.rule_type() != Subscription::ALERT) {
643             continue;
644         }
645         if (subscription.subscriber_information_case() ==
646             Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
647             ALOGW("subscription \"%lld\" has no subscriber info.\"",
648                 (long long)subscription.id());
649             return false;
650         }
651         const auto& itr = anomalyTrackerMap.find(subscription.rule_id());
652         if (itr == anomalyTrackerMap.end()) {
653             ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
654                 (long long)subscription.id(), (long long)subscription.rule_id());
655             return false;
656         }
657         const int anomalyTrackerIndex = itr->second;
658         allAnomalyTrackers[anomalyTrackerIndex]->addSubscription(subscription);
659     }
660     return true;
661 }
662 
initAlarms(const StatsdConfig & config,const ConfigKey & key,const sp<AlarmMonitor> & periodicAlarmMonitor,const int64_t timeBaseNs,const int64_t currentTimeNs,vector<sp<AlarmTracker>> & allAlarmTrackers)663 bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
664                 const sp<AlarmMonitor>& periodicAlarmMonitor,
665                 const int64_t timeBaseNs, const int64_t currentTimeNs,
666                 vector<sp<AlarmTracker>>& allAlarmTrackers) {
667     unordered_map<int64_t, int> alarmTrackerMap;
668     int64_t startMillis = timeBaseNs / 1000 / 1000;
669     int64_t currentTimeMillis = currentTimeNs / 1000 /1000;
670     for (int i = 0; i < config.alarm_size(); i++) {
671         const Alarm& alarm = config.alarm(i);
672         if (alarm.offset_millis() <= 0) {
673             ALOGW("Alarm offset_millis should be larger than 0.");
674             return false;
675         }
676         if (alarm.period_millis() <= 0) {
677             ALOGW("Alarm period_millis should be larger than 0.");
678             return false;
679         }
680         alarmTrackerMap.insert(std::make_pair(alarm.id(), allAlarmTrackers.size()));
681         allAlarmTrackers.push_back(
682             new AlarmTracker(startMillis, currentTimeMillis,
683                              alarm, key, periodicAlarmMonitor));
684     }
685     for (int i = 0; i < config.subscription_size(); ++i) {
686         const Subscription& subscription = config.subscription(i);
687         if (subscription.rule_type() != Subscription::ALARM) {
688             continue;
689         }
690         if (subscription.subscriber_information_case() ==
691             Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
692             ALOGW("subscription \"%lld\" has no subscriber info.\"",
693                 (long long)subscription.id());
694             return false;
695         }
696         const auto& itr = alarmTrackerMap.find(subscription.rule_id());
697         if (itr == alarmTrackerMap.end()) {
698             ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
699                 (long long)subscription.id(), (long long)subscription.rule_id());
700             return false;
701         }
702         const int trackerIndex = itr->second;
703         allAlarmTrackers[trackerIndex]->addSubscription(subscription);
704     }
705     return true;
706 }
707 
initMetricActivations(const ConfigKey & key,const StatsdConfig & config,const int64_t currentTimeNs,const unordered_map<int64_t,int> & logEventTrackerMap,const unordered_map<int64_t,int> & metricProducerMap,vector<sp<MetricProducer>> & allMetricProducers,unordered_map<int,std::vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,std::vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation)708 bool initMetricActivations(const ConfigKey& key, const StatsdConfig& config,
709                            const int64_t currentTimeNs,
710                            const unordered_map<int64_t, int> &logEventTrackerMap,
711                            const unordered_map<int64_t, int> &metricProducerMap,
712                            vector<sp<MetricProducer>>& allMetricProducers,
713                            unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
714                            unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
715                            vector<int>& metricsWithActivation) {
716     for (int i = 0; i < config.metric_activation_size(); ++i) {
717         const MetricActivation& metric_activation = config.metric_activation(i);
718         auto itr = metricProducerMap.find(metric_activation.metric_id());
719         if (itr == metricProducerMap.end()) {
720             ALOGE("Metric id not found in metric activation: %lld",
721                 (long long)metric_activation.metric_id());
722             return false;
723         }
724         const int metricTrackerIndex = itr->second;
725         if (metricTrackerIndex < 0 || metricTrackerIndex >= (int)allMetricProducers.size()) {
726             ALOGE("Invalid metric tracker index.");
727             return false;
728         }
729         const sp<MetricProducer>& metric = allMetricProducers[metricTrackerIndex];
730         metricsWithActivation.push_back(metricTrackerIndex);
731         for (int j = 0; j < metric_activation.event_activation_size(); ++j) {
732             const EventActivation& activation = metric_activation.event_activation(j);
733             auto logTrackerIt = logEventTrackerMap.find(activation.atom_matcher_id());
734             if (logTrackerIt == logEventTrackerMap.end()) {
735                 ALOGE("Atom matcher not found for event activation.");
736                 return false;
737             }
738             const int atomMatcherIndex = logTrackerIt->second;
739             activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(
740                 metricTrackerIndex);
741 
742             ActivationType activationType;
743             if (activation.has_activation_type()) {
744                 activationType = activation.activation_type();
745             } else {
746                 activationType = metric_activation.activation_type();
747             }
748 
749             if (activation.has_deactivation_atom_matcher_id()) {
750                 auto deactivationAtomMatcherIt =
751                         logEventTrackerMap.find(activation.deactivation_atom_matcher_id());
752                 if (deactivationAtomMatcherIt == logEventTrackerMap.end()) {
753                     ALOGE("Atom matcher not found for event deactivation.");
754                     return false;
755                 }
756                 const int deactivationMatcherIndex = deactivationAtomMatcherIt->second;
757                 deactivationAtomTrackerToMetricMap[deactivationMatcherIndex]
758                         .push_back(metricTrackerIndex);
759                 metric->addActivation(atomMatcherIndex, activationType, activation.ttl_seconds(),
760                                       deactivationMatcherIndex);
761             } else {
762                 metric->addActivation(atomMatcherIndex, activationType, activation.ttl_seconds());
763             }
764         }
765     }
766     return true;
767 }
768 
prepareFirstBucket(const vector<sp<MetricProducer>> & allMetricProducers)769 void prepareFirstBucket(const vector<sp<MetricProducer>>& allMetricProducers) {
770     for (const auto& metric: allMetricProducers) {
771         metric->prepareFirstBucket();
772     }
773 }
774 
initStatsdConfig(const ConfigKey & key,const StatsdConfig & config,UidMap & uidMap,const sp<StatsPullerManager> & pullerManager,const sp<AlarmMonitor> & anomalyAlarmMonitor,const sp<AlarmMonitor> & periodicAlarmMonitor,const int64_t timeBaseNs,const int64_t currentTimeNs,set<int> & allTagIds,vector<sp<LogMatchingTracker>> & allAtomMatchers,vector<sp<ConditionTracker>> & allConditionTrackers,vector<sp<MetricProducer>> & allMetricProducers,vector<sp<AnomalyTracker>> & allAnomalyTrackers,vector<sp<AlarmTracker>> & allPeriodicAlarmTrackers,unordered_map<int,std::vector<int>> & conditionToMetricMap,unordered_map<int,std::vector<int>> & trackerToMetricMap,unordered_map<int,std::vector<int>> & trackerToConditionMap,unordered_map<int,std::vector<int>> & activationAtomTrackerToMetricMap,unordered_map<int,std::vector<int>> & deactivationAtomTrackerToMetricMap,vector<int> & metricsWithActivation,std::set<int64_t> & noReportMetricIds)775 bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
776                       const sp<StatsPullerManager>& pullerManager,
777                       const sp<AlarmMonitor>& anomalyAlarmMonitor,
778                       const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
779                       const int64_t currentTimeNs, set<int>& allTagIds,
780                       vector<sp<LogMatchingTracker>>& allAtomMatchers,
781                       vector<sp<ConditionTracker>>& allConditionTrackers,
782                       vector<sp<MetricProducer>>& allMetricProducers,
783                       vector<sp<AnomalyTracker>>& allAnomalyTrackers,
784                       vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
785                       unordered_map<int, std::vector<int>>& conditionToMetricMap,
786                       unordered_map<int, std::vector<int>>& trackerToMetricMap,
787                       unordered_map<int, std::vector<int>>& trackerToConditionMap,
788                       unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
789                       unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
790                       vector<int>& metricsWithActivation,
791                       std::set<int64_t>& noReportMetricIds) {
792     unordered_map<int64_t, int> logTrackerMap;
793     unordered_map<int64_t, int> conditionTrackerMap;
794     unordered_map<int64_t, int> metricProducerMap;
795 
796     if (!initLogTrackers(config, uidMap, logTrackerMap, allAtomMatchers, allTagIds)) {
797         ALOGE("initLogMatchingTrackers failed");
798         return false;
799     }
800     VLOG("initLogMatchingTrackers succeed...");
801 
802     if (!initConditions(key, config, logTrackerMap, conditionTrackerMap, allConditionTrackers,
803                         trackerToConditionMap)) {
804         ALOGE("initConditionTrackers failed");
805         return false;
806     }
807 
808     if (!initMetrics(key, config, timeBaseNs, currentTimeNs, uidMap, pullerManager, logTrackerMap,
809                      conditionTrackerMap, allAtomMatchers, allConditionTrackers, allMetricProducers,
810                      conditionToMetricMap, trackerToMetricMap, metricProducerMap,
811                      noReportMetricIds)) {
812         ALOGE("initMetricProducers failed");
813         return false;
814     }
815     if (!initAlerts(config, metricProducerMap, anomalyAlarmMonitor, allMetricProducers,
816                     allAnomalyTrackers)) {
817         ALOGE("initAlerts failed");
818         return false;
819     }
820     if (!initAlarms(config, key, periodicAlarmMonitor,
821                     timeBaseNs, currentTimeNs, allPeriodicAlarmTrackers)) {
822         ALOGE("initAlarms failed");
823         return false;
824     }
825     if (!initMetricActivations(key, config, currentTimeNs, logTrackerMap, metricProducerMap,
826             allMetricProducers, activationAtomTrackerToMetricMap,
827             deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
828         ALOGE("initMetricActivations failed");
829         return false;
830     }
831 
832     prepareFirstBucket(allMetricProducers);
833 
834     return true;
835 }
836 
837 }  // namespace statsd
838 }  // namespace os
839 }  // namespace android
840