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
37using std::set;
38using std::string;
39using std::unordered_map;
40using std::vector;
41
42namespace android {
43namespace os {
44namespace statsd {
45
46namespace {
47
48bool 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
62bool 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
85bool 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
116bool 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 */
169bool 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
206bool 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
265bool 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
546bool 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
602bool 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
647bool 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