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